如何在枚举值上更改WPF ListView文本颜色

时间:2019-06-30 20:40:27

标签: c# wpf xaml

问题

我是WPF的新手,正在尝试学习。我有一个基本的ListView,它显示有关人的信息,例如姓名,年龄和等级。

如果枚举为“通过”,我希望成绩结果文本为绿色,如果“失败”,我希望为红色,否则文本颜色不变。

我尝试过的事情

我知道您可以使用Foreground =“”将一栏中的所有文本硬编码为绿色,红色等,但这是行不通的。 我尝试实现一个函数,该函数检查列表中的每个枚举是否等于Pass等,但我无法获取它,因此我很困在这里。

XAML

<Grid Margin="10">
        <ListView Name="lvUsers">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Name" Width="120" DisplayMemberBinding="{Binding Name}" />
                    <GridViewColumn Header="Age" Width="50" DisplayMemberBinding="{Binding Age}" />
                    <GridViewColumn Header="Grade" Width="100" DisplayMemberBinding="{Binding Grade}"/>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>

CS

public partial class MainWindow : Window
    {
        public class User
        {
            public string Name { get; set; }
            public int Age { get; set; }
            public Grade Grade { get; set; }
        }

        public MainWindow()
        {
            InitializeComponent();
            List<User> items = new List<User>();
            items.Add(new User() { Name = "John Doe", Age = 42, Grade = Grade.fail });
            items.Add(new User() { Name = "Jane Doe", Age = 39, Grade = Grade.pass });
            items.Add(new User() { Name = "Sammy Doe", Age = 13, Grade = Grade.fail });
            lvUsers.ItemsSource = items;
        }

        public enum Grade
        {
            none = 0,
            pass = 1,
            fail = 2
        };
    }

预期结果

我不希望“成绩”列中的所有文本均为绿色/红色。而且我不想在用户类中添加Color属性。

当用户的枚举值为“通过”时,“成绩”列中的“通过”文本将为绿色。当它为“失败”时,文本将为红色。否则,文本颜色不会更改。

我们非常感谢您的帮助,因为我对此深感困惑。

1 个答案:

答案 0 :(得分:3)

实际上,您可以在这里使用多种选择:

首先,您需要用以下部分之一中的示例替换此GridViewColumn条目:

<GridViewColumn Header="Grade" Width="100" DisplayMemberBinding="{Binding Grade}"/>

1-DataTrigger

MSDN documentation here

这将起作用,但不可重用。

<!-- A custom cell template lets you customise how the cell will display -->
<GridViewColumn Header="Grade" Width="10">
    <GridViewColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Name="GradeText" Text="{Binding Grade}" />
            <!-- define rules on how the ui will change based on the data bound -->
            <DataTemplate.Triggers>
                <!-- see NOTE below for how to get this working -->
                <DataTrigger Binding="{Binding Grade}" Value="{x:Static enum:Grade.pass}">
                    <Setter TargetName="GradeText" Property="Foreground" Value="Green"/>
                </DataTrigger>
                <!-- you can add a second one for fail ;) -->
            </DataTemplate.Triggers>
        </DataTemplate>
    </GridViewColumn.CellTemplate>
</GridViewColumn>

注意,您还需要在声明枚举(full credit to this answer)的地方添加名称空间声明:

xmlns:enum =“ clr-namespace:YourEnumNamespace; assembly = YourAssembly”

2-转换器

MSDN documentation here

这提供了最少的XAML,允许您在其他地方重用该逻辑,如果您真的很在意,请对转换器逻辑进行单元测试。

<!-- A custom cell template lets you customise how the cell will display -->
<GridViewColumn Header="Grade" Width="10">
    <GridViewColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Name="GradeText" Text="{Binding Grade}" Foreground="{Binding Grade, Converter={StaticResource GradeToBrushConverter}}"/>
        </DataTemplate>
    </GridViewColumn.CellTemplate>
</GridViewColumn>

以及转换器代码:

public GradeToBrushConverter : IValueConverter
{
    public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value is Grade grade)
        {
            switch (grade)
            {
                case Grade.pass:
                    return Brushes.Green;
                case fail:
                    return Brushes.Red;
                default:
                    return Brushes.Black; // Or a more sensible default.
            }
        }

        return Brushes.Black;
    }

    // I haven't provided the ConvertBack but you should be able to work this bit out.
}

3-样式

是的,我很欣赏这个示例看起来与第1点非常相似,但是它还有一个好处,那就是,如果您在其他地方声明样式,则可以在多个地方重复使用。

<!-- A custom cell template lets you customise how the cell will display -->
<GridViewColumn Header="Grade" Width="10">
    <GridViewColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Name="GradeText" Text="{Binding Grade}">
                <TextBlock.Style>
                    <Style TargetType="TextBlock">
                        <Setter Property="Foreground" Value="Black"/>
                        <Style.Triggers>
                            <!-- see NOTE below for how to get this working -->
                            <DataTrigger Binding="{Binding Grade}" Value="{x:Static enum:Grade.pass}">
                                <Setter Property="Foreground" Value="Green"/>
                            </DataTrigger>
                            <!-- you can add a second one for fail ;) -->
                        </Style.Triggers>
                    </Style>
                </TextBlock.Style>
            </TextBlock>
        </DataTemplate>
    </GridViewColumn.CellTemplate>
</GridViewColumn>