tags:

views:

350

answers:

3

I may have missed something obvious with WPF, but is it possible to create styles that work hierarchically with the targeted control's child controls? To better explain, think of how CSS works to style HTML. You can hierarchically target controls with CSS via selectors:

div > span em
{
   color: blue;
}

ul.class > li ul li
{
    display: block;
    margin: 0px;
}

Is it possible to achieve the same thing with WPF styles? So far, I have been creating styles for every type of control, or named styles that I directly apply to a control. However, I end up with a hell of a lot more styles than I really intend, and I is nearly impossible to style control structures together as a group.

Thanks for any insight.

UPDATE:

Here is an example of what I would like to be able to do. Note that only the root ListView control has a Style applied. I would like to be able to target any one of the child controls in any one of the CellTemplates without having to directly apply the style to each of those child controls. This keeps my view layout markup more decoupled and isolated from the style markup, giving me a lot more freedom to change the style without having to explicitly create a style for every single control in my entire application.

<Grid>
  <ListView Style="{StaticResource ProcessableItemsListView}">
    <ListView.View>
      <GridView>
        <GridViewColumn Width="10">
          <GridViewColumn.CellTemplate>
            <Grid>
              <CheckBox Value="{Binging ...}" />
            </Grid>
          </GridViewColumn.CellTemplate>
        </GridViewColumn>
        <GridViewColumn Width="*">
          <GridViewColumn.CellTemplate>
            <Grid>
              <TextBlock Text="{Binding ...}" />
            </Grid>
          </GridViewColumn.CellTemplate>
        </GridViewColumn>
        <GridViewColumn Width="80">
          <GridViewColumn.CellTemplate>
            <Grid>
              <Button Command="{Binding ...}">Process</Button>
            </Grid>
          </GridViewColumn.CellTemplate>
        </GridViewColumn>
        <GridViewColumn Width="120">
          <GridViewColumn.CellTemplate>
            <Grid>
              <ProgressBar Value="{Binding ...}" />
            </Grid>
          </GridViewColumn.CellTemplate>
        </GridViewColumn>
      </GridView>
    </ListView.View>
  </ListBiew>
</Grid>
A: 

I'm not one hundred percent sure if I understand you correctly but I think what you want is to style a base class and have that style applied to it's descendants too.

So if, for example, you want to style a ComboBox you could write:

<Style x:Key="ComboBoxStyle" TargetType="ComboBox">
    ...
</Style>

but instead you could also write:

<Style x:Key="ComboBoxStyle" TargetType="Control">
    ...
</Style>

and have that style applied to all descendants of Control instead of just ComboBoxes. The example is (directly and unedited) taken from this blog post.

andyp
Your close, but I need it taken a little farther. Its more along the lines of this: For a particular kind of ListView with a Grid as the root control of its items template, style the button control in Cell X,Y with this style. Does that make more sense?
jrista
yep, I think I understand now what you mean but I've no clue of how to achieve that in WPF. The only way I know of is using a named style and apply it to that button (which seems to be what you want to avoid). Sorry.
andyp
A: 

You can achieve Style inheritance similar to how CSS does it by using the BasedOn attribtue

<Style x:Key="A">
    <Setter Property="Background" Value="Blue" />
</Style> 

<Style x:Key="B" BasedOn="{StaticResource A}">
    <Setter Property="Foreground" Value="Red" />
</Style> 

<Style x:Key="C" BasedOn="{StaticResource A">
    <Setter Property="Foreground" Value="White" />
</Style>

Does that help?

Foovanadil
Its not really style inheritance. Think of a hierarchical structure, say a listview with a Grid in its itemtemplate, and the grid contains different controls in its cells. How do I hierarchically target one of the controls in a grid cell of that listview, without having to explicitly apply the style directly to the control? With CSS, I can target with a selector: .listview .grid button { ... }
jrista
+1  A: 

I would have made this a comment but ran out of characters

Hmmm. Given that the answer from andyp of using implicit styles doesn't solve your problem I can think of two slightly different ways to do this.

One is to make all the controls in your grid cells be simple content controls and bind a data object to the Content property of the control. Then you can create implicit styles that are targeted at your data object, instead of the the UI control type. This is pretty much the same thing andyp suggested but just looking at it from a data perspective (which may not work in your scenario)

The other solution I could think of is to create a style targeted at some root UIElement that all of your grid cell controls inherit from. In the style add a trigger to swap certain properties of your control based on some value (Name, Tag, some other data binding).

Not sure that either of those will get what you want but it's worth a shot.

Also, could you post a code snippet that shows more clearly what you are trying to accomplish. There may be a much simpler way to solve this problem that I am just missing.

Foovanadil