CellStyle based on RowStyle in WPF

纵饮孤独 提交于 2019-12-07 06:05:10

问题


I have a WPF DataGrid represented in XAML. I'm using a RowStyle for my grid's TableView but also need to set some properties for specific cells. I need those cells to have the properties of the row style and apply the extra properties from the cell style on top of those.

What I would need is something like this, although this doesn't work as it's saying:

Target type 'CellContentPresenter' is not convertible to base type 'GridRowContent'

<Style x:Key="MyGridRowStyle"
    BasedOn="{StaticResource {themes:GridRowThemeKey ResourceKey=RowStyle}}"
    TargetType="{x:Type dxg:GridRowContent}">
    <Setter Property="Height" 
        Value="25" />
        <Style.Triggers>
        ...
    </Style.Triggers>
</Style>

<Style x:Key="MyCellStyle" 
    BasedOn="{StaticResource MyGridRowStyle}" 
    TargetType="{x:Type dxg:CellContentPresenter}">
    <Style.Triggers>
        ...
    </Style.Triggers>
</Style>

I've also tried not specifying the BasedOn property for MyCellStyle but that doesn't work either.

I use the MyCellStyle like this:

<dxg:GridColumn Header="My Header"
                FieldName="MyFieldName"
                Width="100"
                CellStyle="{StaticResource MyCellStyle}" />

and MyGridRowStyle like this on the TableView:

RowStyle="{StaticResource MyGridRowStyle}"

How can I make the cell style only change the properties specified in MyCellStyle and use the values specified in MyGridRowStyle for the other properties?


回答1:


based on normal WPF DataGrid you could try this and expand it for dxg the class DataGridCell is derived from ContentControl (that is a child from Content). the class DataGridRow is derived from Control.

now you could try the following:

<Style x:Key="BaseStyle" TargetType="Control" >
    <!-- Maybe add BaseStyle / theme here with BasedOn -->
    <Setter Property="Height" Value="25" />
    <!-- Row and Column defaults -->
</Style>
<Style x:Key="MyGridRowStyle" BasedOn="{StaticResource BaseStyle}"
       TargetType="DataGridRow">
    <!-- Row specific implementation -->
</Style>
<Style x:Key="MyCellStyle" BasedOn="{StaticResource BaseStyle}"
       TargetType="DataGridCell">
    <!-- Column specific implementation -->
</Style>

summary: use base type of both Row and Column classes for your BaseStyle and use this one as BasedOn. For dxg you can extend it by your own...




回答2:


You can't base a CellContentPresenter style on a GridRowContent style. These are two completely different types and just because they may happen to have some properties that have the same name these are still completely different and independant properties with no relationship to each other.

The best thing you can do is to define the common values as separate resources and use these resources in both styles, e.g.:

<Window.Resources>
  <s:Double x:Key="commonHeight">25</s:Double>
  <SolidColorBrush x:Key="commonBg">Red</SolidColorBrush>

  <Style x:Key="MyCellStyle" TargetType="{x:Type dxg:CellContentPresenter}">
    <Setter Property="Height" Value="{StaticResource commonHeight}" />
    <Setter Property="Background" Value="{StaticResource commonBg}" />
  </Style>

  <Style x:Key="MyGridRowStyle" BasedOn="{StaticResource {themes:GridRowThemeKey ResourceKey=RowStyle}}" TargetType="{x:Type dxg:GridRowContent}">
    <Setter Property="Height" Value="{StaticResource commonHeight}" />
    <Setter Property="Background" Value="{StaticResource commonBg}" />
 </Style>
</Window.Resources>

But you still need to define all setters in both styles.




回答3:


My understanding of the question: values of the cell style should change based off of values in the style of the row it is in.

Trigger off of value

Here is a simple working example (test it by changing the DataGridRow Background to Red, you will notice that the cell's foreground changes to Blue):

 <DataGrid>
    <DataGrid.RowStyle>
        <Style TargetType="DataGridRow">
            <Setter Property="Background" Value="White"/>
        </Style>
    </DataGrid.RowStyle>
    <DataGrid.CellStyle>
        <Style TargetType="DataGridCell">
            <Style.Triggers>
                <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=DataGridRow, Mode=FindAncestor}, Path=Background}" Value="Red">
                    <Setter Property="Foreground" Value="Blue"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </DataGrid.CellStyle>
</DataGrid>

You can do a similar binding to directly set properties of the CellStyle to the value of properties of the row it is in.

Relative bind directly to a property

<DataGrid x:Name="dataGrid1" ItemsSource="{Binding Collection}">
    <DataGrid.RowStyle>
        <Style TargetType="DataGridRow">
            <Setter Property="Height" Value="20"/>
        </Style>
    </DataGrid.RowStyle>
    <DataGrid.CellStyle>
        <Style TargetType="DataGridCell">
            <Setter Property="FontSize" Value="{Binding RelativeSource={RelativeSource AncestorType=DataGridRow, Mode=FindAncestor}, Path=Height}"/>
        </Style>
    </DataGrid.CellStyle>
</DataGrid>

Explanation

RelativeBinding works due to the fact that DataGridCells are eventual children of DataGridRows as can been seen in this screenshot of the visual tree of a DataGrid:



来源:https://stackoverflow.com/questions/40889382/cellstyle-based-on-rowstyle-in-wpf

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!