On The Net Again
On The Net Again

Reputation: 305

Is there an element selector in XAML Styles like there is in CSS?

In CSS, you can do this:

#menu, #nav-bar, #data-grid {
    background: autumn-red;
}

Is there something similar in XAML styles?

Upvotes: 2

Views: 925

Answers (2)

Andy
Andy

Reputation: 12276

The wpf selector equivalent is control type and a style can target only one.

A given control can only have one style applied.

Styling can be inherited from a base style using basedon.

It is usual to put styling in resource dictionaries and merge them where needed - often this is app.xaml so the styling is used across an application.

You can, however, put styling in the resources of a specific control or a parent. EG.

<Window.Resources>
    <Style x:Key="BaseStyle" TargetType="Control">
        <Setter Property="Background" Value="Red"/>
    </Style>
    <Style TargetType="DataGrid" BasedOn="{StaticResource BaseStyle}"/>
    <Style TargetType="Menu" BasedOn="{StaticResource BaseStyle}"/>
</Window.Resources>

The targettype you choose must have the property you wish to set. This also applies where you're inheriting using basedon.

There is no "cascading" of styles.

There are a few complications.

WPF applies the value from a style to a dependency property. DPs have a bunch of extra functionality and one of those properties is "Inherits". You can set a value on a parent and this is inherited down the visual tree of controls. This is how font and datacontext applied to a window are propogated down to it's children.

Only some DPs inherit in this way but those that do offer a convenient way to apply a value to a whole container's content.

All in all it's fairly obvious that CSS is more flexible in this way.

It's worth mentioning there are some other mechanisms in wpf which offer flexibility. This goes beyond just setting the background of something but I guess your question just has background for simplicity.

WPF has:

Data templates - which can produce as rich as you can imagine chunk of UI when a piece of data of a specific type is presented.

User Controls (pages etc) - which encapsulate UI in a re-usable manner.

Triggers, datatriggers and visual state manager - which allow you to set or animate values on dependency properties conditionally.

Since WPF controls are "lookless" and their templates defined in xaml, you can do some quite surprising things. Like template a togglebutton as a textblock and toggle it's text on clicking. Some implications of this are very powerful. Some are counter intuitive. https://social.technet.microsoft.com/wiki/contents/articles/29866.aspx

Upvotes: 0

Sorin
Sorin

Reputation: 169

This is the closest that I can think about - although it's not a "selector" it still allows you to define the style once for multiple element instances:

Assuming your Menu, ToolBar, and DataGrid WPF components all have a common base type that is or inherits from Control, you you can define a single Style with a specific x:Key, e.g. CommonStyle, in your container's Resources, with TargetType set to that common component ancestor type.

The style can have a Setter for Background, and/or Foreground, or FontSize properties of Control, for example.

Then you can point to that Style from each instance using Style="{StaticResource CommonStyle}".

The caveat is that some type implementations (actually their ControlTemplates) do NOT use the property values defined on the common ancestor type at all. For example, DataGrid doesn't respect Background for rows (but it does for a small separator between them and for the region under the rows, if the space is larger - add Height="200" to its instance to see), Toolbar doesn't use Foreground, but FontSize is used by all of DataGrid, Menu and ToolBar.

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <Style x:Key="CommonStyle" TargetType="Control">
            <Setter Property="Background" Value="Yellow"/>
            <Setter Property="Foreground" Value="Red"/>
            <Setter Property="FontSize" Value="30"/>
        </Style>
    </Window.Resources>
    <StackPanel>
        <Menu Style="{StaticResource CommonStyle}">
            <MenuItem Header="Test"/>
        </Menu>
        <ToolBar Style="{StaticResource CommonStyle}">
            <Button Content="Test"/>
        </ToolBar>
        <DataGrid Style="{StaticResource CommonStyle}">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding}" Header="Item"/>
            </DataGrid.Columns>
            <sys:String>Test</sys:String>
        </DataGrid>
    </StackPanel>
</Window>

Screenshot

I hope it helps.

Upvotes: 1

Related Questions