【问题标题】:Set WPF Cell Style Using A Converter使用转换器设置 WPF 单元格样式
【发布时间】:2014-03-12 14:22:06
【问题描述】:

我有两种 WPF 单元格样式,我想基于转换器应用它们。 我是下面的示例,我正在尝试更改背景颜色(在实际应用中我会更改更多,但这不是问题的重点,所以我只是在简化)。

<Style TargetType="{x:Type DataGridCell}" x:Key="WinCellStyle">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridCell}">
                <Border x:Name="border"
                        Background="LightGreen"
                        BorderBrush="Transparent"
                        BorderThickness="1"
                        SnapsToDevicePixels="True">

                    <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style TargetType="{x:Type DataGridCell}" x:Key="LossCellStyle">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridCell}">
                <Border x:Name="border"
                        Background="LightSalmon"
                        BorderBrush="Transparent"
                        BorderThickness="1"
                        SnapsToDevicePixels="True">

                    <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

然后我有一个转换器:

public class AmountToCellStyleConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {

        var valueAsDecimal = (decimal?) value;
        if (valueAsDecimal > 0)
        {
            return Application.Current.FindResource("WinCellStyle") as Style;
        }
        return Application.Current.FindResource("LossCellStyle") as Style;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }       
}

然后如何在单元格样式中调用它?

XAML:

<Window.Resources>
    <converter:AmountToCellStyleConverter  x:Key="AmountToCellStyleConverter"/>      
</Window.Resources>

...

<DataGridTextColumn CellStyle="{Binding ??? What goes here}" Binding="{Binding Path=MarketBookSelection.TotalWagerStakeWin, StringFormat=N2}" Header="Stake Win" Width="Auto" />

也许答案是这是不可能的,我需要走其他路线?

【问题讨论】:

    标签: c# wpf xaml datagrid


    【解决方案1】:

    绑定在 DataGridColumn 的 CellStyle 中不起作用,因此请尝试为 TextBox 目标类型而不是 DataGridCell 创建样式,并像这样编写 DataGridTemplateColumn

    <DataGrid.Resources>
        <local:AmountToCellStyleConverter x:Key="StyleConverter" /> 
    </DataGrid.Resources>
    
    ...
    
    <DataGridTemplateColumn Width="1.5*" 
                            Header="SimpleHeader"
                            IsReadOnly="False">
    
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>                           
                <TextBox Style="{Binding Path=NumberValue, Converter={StaticResource StyleConverter}}"
                         Text="{Binding Path=NumberValue}" />                            
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
    

    或者写入一个值而不是两个,在这种情况下,转换器的输入值类型将是String

    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>                           
            <TextBox Style="{Binding Path=Text,
                                     RelativeSource={RelativeSource Mode=Self}, 
                                     Converter={StaticResource StyleConverter}}"
                     Text="{Binding Path=NumberValue}" />                            
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    

    TextBox 的样式位于App.xaml

    <Application.Resources>
        <Style x:Key="WinCellStyle" TargetType="{x:Type TextBox}">
            <Setter Property="SnapsToDevicePixels" Value="True" />
    
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TextBoxBase}">
                        <Border Background="LightGreen"
                                BorderThickness="1">
    
                            <ScrollViewer x:Name="PART_ContentHost" 
                                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    
        <Style x:Key="LossCellStyle" TargetType="{x:Type TextBox}">
            <Setter Property="SnapsToDevicePixels" Value="True" />
    
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TextBox}">
                        <Border Background="LightSalmon"
                                BorderThickness="1">
    
                            <ScrollViewer x:Name="PART_ContentHost" 
                                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Application.Resources>
    

    Converter 看起来像这样:

    public class AmountToCellStyleConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var valueAsDecimal = (int)value;
    
            if (valueAsDecimal > 0)
            {
                return Application.Current.FindResource("WinCellStyle") as Style;
            }
    
            return Application.Current.FindResource("LossCellStyle") as Style;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    或者您可以这样做:将转换器的逻辑更改为返回 TrueFalse,然后在 CellStyle 中您可以这样写:

    <DataGridTextColumn Header="SimpleHeader"                                    
                        Width="1.5*" 
                        Binding="{Binding Path=NumberValue}">
    
        <DataGridTextColumn.CellStyle>
            <Style TargetType="{x:Type DataGridCell}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=NumberValue, Converter={StaticResource MyConverter}}" Value="True">
                        <Setter Property="Background" Value="Yellow" />
                        <Setter Property="BorderThickness" Value="1" />
                    </DataTrigger>
    
                    <DataTrigger Binding="{Binding Path=NumberValue, Converter={StaticResource MyConverter}}" Value="False">
                        <Setter Property="Background" Value="Red" />
                        <Setter Property="BorderThickness" Value="1" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </DataGridTextColumn.CellStyle>
    </DataGridTextColumn>
    

    【讨论】:

    • 这很奏效,只是想知道单元格样式是否有任何原因不能采用更方便的绑定?
    • @DermFrench:这是因为DataGridColumns 与DataGrid 的VisualTree 不同。因此,默认情况下它不会继承 DataGrid 的 DataContext 并且 Binding 不起作用。除了我的回答之外,您还可以使用代理来继承 DataContext 讨论here
    猜你喜欢
    • 1970-01-01
    • 2010-11-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多