有条件地设置 GridViewColumn 单元格模板

3

我有一个视图DisplayTestsView.cs,在该视图中我有:

<ListView ItemsSource="{Binding SelectedTechnician.Tests}"
SelectedItem="{Binding SelectedTest}" x:Name="AvailableTestsListView" Height="140">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Id" Width="auto" DisplayMemberBinding="{Binding Id}"/>
            <GridViewColumn Header="Test" Width="auto" DisplayMemberBinding="{Binding TestTypeName}"/>
            <GridViewColumn Header="Status" Width="auto" DisplayMemberBinding="{Binding StutusTypeName}"/>
        </GridView>
    </ListView.View>
</ListView>

我希望根据条件将StatusTypeName单元格文本的TextColor设置为特定颜色。例如,如果StatusTypeName等于"Incomplete",则我希望单元格中的文本变成红色。

从视图中可以看出,测试(实体)列表是SelectedTechnician.Tests,而SelectedTechnician是ViewModel(DisplayTestsViewModel)上的属性。

我想必须使用GridViewColumn的CellTemplate属性,但由于对如何有条件地操作模板(通常)知之甚少,因此不确定从哪里开始。

即使CellTemplate与此无关,如何按类似上述描述的方式有条件地设置GridViewColumn单元格的文本以更改颜色呢?

1个回答

5

您说得对,CellTemplate是实现颜色更改的正确位置。

您可以像这样做(警告-未经测试):

<ListView ItemsSource="{Binding SelectedTechnician.Tests}"
SelectedItem="{Binding SelectedTest}" x:Name="AvailableTestsListView" Height="140">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Id" Width="auto" DisplayMemberBinding="{Binding Id}"/>
            <GridViewColumn Header="Test" Width="auto" DisplayMemberBinding="{Binding TestTypeName}"/>
            <GridViewColumn Header="Status" Width="auto">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock
                            Text="{Binding StatusTypeName}"
                            Foreground="{Binding StatusTypeName, Converter={StaticResource StatusTypeNameToBrushConverter}}" />
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
        </GridView>
    </ListView.View>
</ListView>

StatusTypeNameToBrushConverter 将会像这样:

public class StatusTypeNameToBrushConverter : IValueConverter
{
    public object Convert(
        object value, Type targetType, object parameter, CultureInfo culture)
    {
        var statusTypeName = (string)value;
        switch (statusTypeName)
        {
            case "Incomplete":
                return Brushes.Red;
            default:
                return Brushes.Black;
        }
    }

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

那么,将StatusTypeNameToBrushConverter的逻辑存储在ViewModel中是否可能?如果不行,仅使用触发器能否实现类似的功能?我刚从工作回家路上了解到了它们。非常感谢迄今为止提供的帮助。 - Isaiah Nelson
实际上,请忽略上面的评论,我已经想通了,并且您的答案事实上可以直接使用。我添加了一个用户控件资源字典来限定您创建的StaticResource的位置。 - Isaiah Nelson
如果你认为我的问题写得很好或者研究得很透彻,请不要忘记给我点赞或者顶起来。我总是喜欢知道自己做对了什么。 - Isaiah Nelson
1
很高兴你解决了问题。实际上,我认为在ViewModel中放置转换器逻辑没有任何问题,尽管这在某种程度上是有争议的。有些人认为ViewModel应该对与视图相关的问题(如画笔、大小、线条粗细等)保持不可知状态,而另一些人则认为ViewModel的工作应该是准备视图所需的所有数据。通常情况下,我觉得把所有东西都放在ViewModel中会更方便(特别是如果你发现自己需要多值转换器),但编写转换器类可以轻松实现重用。顺便说一句,我+1了你的问题。 - devuxer
我将转换器放在它自己的类中而不是ViewModel中,我开始感觉ViewModel有些臃肿了。你提到这种做法周围的争议是完全有道理的,我注意到这样的情况确实迫使人们考虑哪个层有什么责任。谢谢你的支持。如果只是问问题,很难获得声望 :) - Isaiah Nelson
1
你可能想要了解一下 Fody.PropertyChanged(https://github.com/Fody/PropertyChanged/wiki)。它基本上可以帮助你省去编写 INotifyPropertyChanged 代码的麻烦,从而使视图模型更加简洁易维护。 - devuxer

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