简体   繁体   English

以编程方式更改 ListView 行的背景颜色(wpf)

[英]Change background color of ListView row programmatically (wpf)

I have a class that populates a ListView by passing a list of objects.我有一个 class 通过传递对象列表来填充 ListView。 The class uses reflection to see the properties of each object in order to generate the ListView. class 使用反射查看每个 object 的属性以生成 ListView。 How could I change the background color of a row in the ListView.如何更改 ListView 中一行的背景颜色。

This page does exactly what I am looking for.这个页面正是我正在寻找的。 The only problem is that my ListView is bound to the list of objects.唯一的问题是我的 ListView 绑定到对象列表。 In other words each item of the ListView is an object that is bound instead of a ListViewItem.换句话说,ListView 的每个项目都是一个绑定的 object,而不是一个 ListViewItem。 I am assuming that is the reason why I cannot cast some item in the ListView to a ListViewItem.我假设这就是我无法将 ListView 中的某些项目转换为 ListViewItem 的原因。 For example when I do this:例如,当我这样做时:

ListViewItem someItem = (ListViewItem)listView1.Items[0];

I get an InvalidcastException because if I where to physically add the objects to the ListView like:我得到一个 InvalidcastException 因为如果我将对象物理添加到 ListView 的位置,例如:

listview.items.add(someObject) then this will work, but because I am binding the list to the ListView that line does not work. listview.items.add(someObject) 那么这将起作用,但是因为我将列表绑定到 ListView 该行不起作用。 I think that is the reason why I am not able to cast.我想这就是我不能投的原因。 The reason why I want to cast it is becasue a ListViewItem has a Background property.我想投它的原因是因为 ListViewItem 有一个 Background 属性。

EDIT编辑

I am able to do that with the first 12 objects I have tried the folowing:我可以用我尝试过的前 12 个对象来做到这一点:

for (int i = 0; i < listView1.Items.Count; i++)
{
    var lvitem = listView1.ItemContainerGenerator.ContainerFromIndex(i) as ListViewItem;
    lvitem.Foreground = Brushes.Green;                
}

and I get this error:我得到这个错误:

第一次尝试

and I also have tried this:我也试过这个:

foreach (Tiro t in listView1.Items)
{
    var lvitem = listView1.ItemContainerGenerator.ContainerFromItem(t) as ListViewItem;
    if (t.numero == 0 || t.numero == 37)
    {
        //lvitem.Background = Brushes.Green;
        lvitem.Foreground = Brushes.Green;
    }
    else if (t.numero % 2 == 0)
    {
        //lvitem.Background = Brushes.Red;
        lvitem.Foreground = Brushes.Red;
    }
    else
    {
        //lvitem.Background = Brushes.Gray;
        lvitem.Foreground = Brushes.Black;
    }

}

and I get the same error:我得到同样的错误:

在此处输入图像描述

I don't understand why lvitem is null after the 12 iteration?我不明白为什么 lvitem 在 12 次迭代后是 null ?

It only works with the items that are being displayed....它仅适用于正在显示的项目....

You need to introduce ViewModels instead of shredding the WPF UI.您需要引入 ViewModels 而不是粉碎 WPF UI。 eg I could create one as follows例如我可以创建一个如下

public class ItemVM : INotifyPropertyChanged // if you want runtime changes to be reflected in the UI
{
  public string Text {... raise property change in setter }
  public Color BackgroundColor {... ditto... }
}

Next create a list of such objects as a property in your DataContext so that your ListView can bind to it.接下来,在您的 DataContext 中创建一个此类对象的列表作为属性,以便您的 ListView 可以绑定到它。

// e.g. MainWindow
    public IEnumerable<ItemVM> Items { get; set; }

Now all you need to do is bind your ListView to this collection and wire up the DataContext of the UI properly现在您需要做的就是将您的 ListView 绑定到此集合并正确连接 UI 的 DataContext

       <ListView x:Name="MyListView" ItemsSource="{Binding Items}" HorizontalContentAlignment="Stretch">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Text}">
                    <TextBlock.Background>
                        <SolidColorBrush Color="{Binding BackgroundColor}"/>
                    </TextBlock.Background>
                    </TextBlock>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        <Button Click="Button_Click" Content="Go PaleGreen"/>

Now changing the background color is easy.现在更改背景颜色很容易。 Just set the property of the corresponding ItemVM object to the Color you want.只需将对应的 ItemVM object 的属性设置为您想要的颜色即可。 eg to set all items to go PaleGreen例如将所有项目设置为 go PaleGreen

private void Button_Click(object sender, RoutedEventArgs e)
    {
        foreach (var item in Items)
            item.BackgroundColor = Colors.PaleGreen;
    }

You could use the ItemContainerGenerator , eg:您可以使用ItemContainerGenerator ,例如:

var lvitem = listView.ItemContainerGenerator.ContainerFromItem(item) as ListViewItem;
var lvitem = listView.ItemContainerGenerator.ContainerFromIndex(0) as ListViewItem;

However by default the ListView is virtualizing, this means ListViewItems are created on the fly as needed (only if the item is actually visible in the list), so the above methods will not return containers for items which are currently not visible.但是默认情况下, ListView是虚拟化的,这意味着ListViewItems是根据需要动态创建的(仅当项目在列表中实际可见时),因此上述方法不会为当前不可见的项目返回容器。

This being the case it usually is preferable to define a binding on the Background property via a Setter in the ItemContainerStyle .在这种情况下,通常最好通过ItemContainerStyle中的Setter定义Background属性的绑定。

When using the ItemContainerGenerator then be aware that the containers are generated asynchronously.使用ItemContainerGenerator时,请注意容器是异步生成的。 The generator exposes a status changed event you could listen to:生成器公开了一个您可以收听的状态更改事件:

listView.ItemContainerGenerator.StatusChanged += new EventHandler(ContainerStatusChanged);     

private void ContainerStatusChanged(object sender, EventArgs e)  
{  
    if (listView.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)  
    {  
        foreach (Tiro t in listView1.Items)
        {
            ...
        }
    }  
}

Not sure if that will create any weird drawing effects (flickering) or not.不确定这是否会产生任何奇怪的绘图效果(闪烁)。

Another option instead of building the listview items in code is to you use data templates.另一个替代在代码中构建列表视图项的选择是使用数据模板。 You might have to add a few properties to your view model for display purposes though.您可能需要向视图 model 添加一些属性以用于显示目的。

Assuming the items in your ListBox are of type Foo , and in the ListBox you will display Foo.ItemInfo for each Foo item, and finally let's say there's a property called Status that determines how you want each Foo.ItemInfo to be displayed in the ListBox with respect to the background, foreground, font style, and tooltip text.假设您的 ListBox 中的项目是Foo类型的,并且在 ListBox 中,您将为每个 Foo 项目显示Foo.ItemInfo ,最后假设有一个名为Status的属性确定您希望每个Foo.ItemInfo如何在 ListBox 中显示关于背景、前景、字体样式和工具提示文本。 Based on these requirements, add the following in your XAML:根据这些要求,在您的 XAML 中添加以下内容:

<ListBox FontFamily="Courier New"
         HorizontalAlignment="Left"
      ...
      ...other ListBox attributes...
      ...
    <ListBox.Resources>
        <local:BGConverter x:Key="BackgroundConverter"/>
        <local:FGConverter x:Key="ForegroundConverter"/>
        <local:FSConverter x:Key="FontStyleConverter"/>
        <local:TTConverter x:Key="ToolTipConverter"/>
    </ListBox.Resources>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding ItemInfo}"
                Background="{Binding Converter={StaticResource BackgroundConverter}}"
                FontStyle="{Binding Converter={StaticResource FontStyleConverter}}"
                Foreground="{Binding Converter={StaticResource ForegroundConverter}}"
                ToolTip="{Binding Converter={StaticResource ToolTipConverter}}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Next, add the following into your MainWindow.xaml.cs (or whatever you've named the XAML's accompanying file) in C#:接下来,将以下内容添加到 C# 中的 MainWindow.xaml.cs(或任何您命名的 XAML 随附文件)中:

public class BGConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        Foo foo = (Foo)value;
        string bgColor = "Gray";

        switch(foo.Status)
        {
            case 0: 
                bgColor = "White";
                break;

            case 1: 
                bgColor = "Cyan";
                break;

            case 2: 
                bgColor = "Yellow";
                break;
        }

        return bgColor;
    }

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

public class FSConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        Foo foo = (Foo)value;
        string fStyle = "Normal";

        switch(foo.Status)
        {
            case 0:
                fStyle = "Normal";
                break;

            case 1: 
                fStyle = "Oblique";
                break;

            case 2: 
                fStyle = "Italic";
                break;
        }

        return fStyle;
    }

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


public class FGConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        Foo foo = (Foo)value;
        string fgColor = "Black";

        switch(foo.Status)
        {
            case 0: 
                fgColor = "Blue";
                break;

            case 1: 
                fgColor = "Brown";
                break;

            case 2: 
                fgColor = "DarkBlue";
                break;
        }

        return fgColor;
    }

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

public class TTipConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        Foo foo = (Foo)value;
        string ttText = "No tool tips for this item.";

        switch(foo.Status)
        {
            case 0: 
                ttText = "The item has not been processed";
                break;

            case 1: 
                ttText = "The item has been processed but not saved";
                break;

            case 2: 
                ttText = "The item has been processed and saved";
                break;
        }

        return ttText ;
    }

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

This is one way I've found that works...there's no doubt many other ways, and your mileage may vary...这是我发现可行的一种方法……毫无疑问还有很多其他方法,而且你的里程可能会有所不同……

In any event, HTH无论如何,HTH

After some googling i found out my own solution I am using Listview.ItemsSource and as source i use List Then i can set background of specify ListViewItem in List, and just refresh listview.经过一番谷歌搜索后,我发现了我自己的解决方案,我正在使用 Listview.ItemsSource 并且作为源我使用 List 然后我可以在 List 中设置指定 ListViewItem 的背景,然后刷新 listview。

XAML: XAML:

 <ListView x:Name="listView" ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Auto" Grid.Row="1">
                <ListView.View>
                    <GridView>
                        <GridViewColumn Header="IP"  DisplayMemberBinding="{Binding IP}" Width="Auto"/>
                        <GridViewColumn Header="PING" DisplayMemberBinding="{Binding Ping}" Width="Auto"/>
                        <GridViewColumn Header="Host Name" DisplayMemberBinding="{Binding DNS}" Width="Auto"/>
                        <GridViewColumn Header="Mac" DisplayMemberBinding="{Binding MAC}" Width="Auto"/>
                        <GridViewColumn Header="Výrobce" DisplayMemberBinding="{Binding Manufacturer}" Width="Auto"/>
                    </GridView>
                </ListView.View>
            </ListView>

Fill ListView with Items with Gray Background:用灰色背景的项目填充 ListView:

    List<ListViewItem> ITEMS = new List<ListViewItem>();
    private void button_Click(object sender, RoutedEventArgs e)
    {
        for (int i = 1; i < 20; i++)
        {
            ListViewItem OneItem = new ListViewItem();
            OneItem.Background = Brushes.LightGray;
            OneItem.Content = new Device() { IP = "1.1.1.1", Ping = "30ms", DNS = "XYZ", MAC = "2F:3C:5F:41:F9", Manufacturer = "Intel" };
            ITEMS.Add(OneItem);
            listView.ItemsSource = ITEMS;
        }
        listView.Items.Refresh();
    }
    public class Device
    {
        public string IP { get; set; }
        public string Ping { get; set; }
        public string DNS { get; set; }
        public string MAC { get; set; }
        public string Manufacturer { get; set; }
    }

Create Method for Row Change Color:创建行更改颜色的方法:

    private void ChangeRowColor(int RowIndex,SolidColorBrush NewBackground)
    {
        ITEMS[RowIndex].Background = NewBackground;
        listView.Items.Refresh();
    }

And use it:并使用它:

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        ChangeRowColor(4, Brushes.Green);
    }
  List<ListViewItem> ITEMS = new List<ListViewItem>();
private void loadListView(ListView lv)
{
    int numberOfRows = 20;
    string[] student_number, first_name, last_name, middle_name, extension, course, year, section;
      //    ...... Assign values to the arrays above...
    for (int h = 0; h <= numberOfRows - 1; h++)
        {
            ListViewItem OneItem = new ListViewItem();
            OneItem.Background = course[h] == "Grade" ? Brushes.Red : Brushes.Transparent; //Decide the color of the Row
            OneItem.Content = new Student
            {
                Student_Number = student_number[h],
                Course = course[h],
                Section = section[h],
                Year = year[h],
                FullName = first_name[h] + " " + middle_name[h] + ". " + last_name[h] + " " + extension[h]
            };
            ITEMS.Add(OneItem);
            lv.ItemsSource = ITEMS;
        }
        lv.Items.Refresh();
}
public class Student
{
    public string Student_Number { get; set; }
    public string FullName { get; set; }
    public string Course { get; set; }
    public string Section { get; set; }
    public string Year { get; set; }
}

output screenshot output 截图

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM