使用转换器设置WPF单元格样式

5

我有两种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" />

也许答案是这不可能实现,我需要走其他路线吗?
1个回答

3

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>

转换器 的外观如下:

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
2
@DermFrench:这是因为DataGridColumns不在与DataGrid相同的VisualTree中。因此,默认情况下,它不会继承DataGrid的DataContext,*Binding*也无法工作。除了我的答案之外,你还可以使用一个代理来继承DataContext,具体讨论请参见这里 - Anatoliy Nikolaev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接