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

我有一个类,通过传递一个对象列表填充ListView。 该类使用reflection来查看每个对象的属性,以便生成ListView。 我怎么能改变ListView中行的背景颜色。

这个页面完全符合我的要求。 唯一的问题是我的ListView绑定到对象列表。 换句话说,ListView的每个项都是绑定的对象而不是ListViewItem。 我假设这就是我无法将ListView中的某些项目转换为ListViewItem的原因。 例如,当我这样做时:

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

我得到一个InvalidcastException,因为如果我将对象物理添加到ListView,如:

listview.items.add(someObject)然后这将工作,但因为我将列表绑定到ListView该行不起作用。 我认为这就是我无法施展的原因。 之所以我想要它,是因为ListViewItem有一个Background属性。

编辑

我能够用我尝试过的前12个对象来做到这一点:

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

我收到此错误:

第一次尝试

我也试过这个:

 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; } } 

我得到同样的错误:

在此处输入图像描述

我不明白为什么lvitem在12次迭代后为空?

它只适用于正在显示的项目….

使用ItemContainerGenerator注意容器是异步生成的。 生成器公开您可以收听的状态更改事件:

 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) { ... } } } 

不确定是否会产生任何奇怪的绘画效果(闪烁)。

另一种选择是在代码中构建listview项,而是使用数据模板。 您可能必须向视图模型添加一些属性以用于显示目的。

您需要引入ViewModels而不是粉碎WPF UI。 例如,我可以创建一个如下

 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... } } 

接下来,在DataContext中创建一个这样的对象列表作为属性,以便ListView可以绑定到它。

 // eg MainWindow public IEnumerable Items { get; set; } 

现在您需要做的就是将ListView绑定到此集合并正确连接UI的DataContext

              

现在改变背景颜色很容易。 只需将相应ItemVM对象的属性设置为所需的颜色即可。 例如,将所有项目设置为PaleGreen

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

您可以使用ItemContainerGenerator ,例如:

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

但是默认情况下ListView是虚拟化的,这意味着ListViewItems是根据需要动态创建的(仅当项目在列表中实际可见时),因此上述方法不会返回当前不可见的项目的容器。

在这种情况下,通常最好通过ItemContainerStyleSetterBackground属性上定义绑定。

假设ListBox中的项目是Foo类型,并且在ListBox中,您将为每个Foo项目显示Foo.ItemInfo ,最后假设有一个名为Status的属性,它确定您希望每个Foo.ItemInfo如何显示在ListBox中关于背景,前景,字体样式和工具提示文本。 根据这些要求,在XAML中添加以下内容:

             

接下来,在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(); } } 

这是我发现有效的一种方式……毫无疑问还有许多其他方式,你的里程可能会有所不同……

无论如何,HTH

经过一些谷歌搜索我找到了我自己的解决方案我使用Listview.ItemsSource和作为源我使用列表然后我可以设置列表中指定ListViewItem的背景,只刷新列表视图。

XAML:

             

使用带灰色背景的项填充ListView:

  List ITEMS = new List(); 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; } } 

为行更改颜色创建方法:

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

并使用它:

  private void button1_Click(object sender, RoutedEventArgs e) { ChangeRowColor(4, Brushes.Green); } 
  List ITEMS = new List(); 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; } } 

输出截图