我有一个通过传递对象列表来填充ListView的类。该类使用反射来查看每个对象的属性,以便生成ListView。如何更改ListView中行的背景颜色。
这page完全符合我的要求。唯一的问题是我的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次迭代后为空?
它仅适用于正在显示的项目....
答案 0 :(得分:10)
您需要引入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可以绑定到它。
// e.g. MainWindow
public IEnumerable<ItemVM> Items { get; set; }
现在您需要做的就是将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"/>
现在更改背景颜色很容易。只需将相应ItemVM对象的属性设置为所需的颜色即可。例如将所有项目设置为PaleGreen
private void Button_Click(object sender, RoutedEventArgs e)
{
foreach (var item in Items)
item.BackgroundColor = Colors.PaleGreen;
}
答案 1 :(得分:4)
您可以使用ItemContainerGenerator
,例如:
var lvitem = listView.ItemContainerGenerator.ContainerFromItem(item) as ListViewItem;
var lvitem = listView.ItemContainerGenerator.ContainerFromIndex(0) as ListViewItem;
但是默认情况下ListView
是虚拟化的,这意味着ListViewItems
会根据需要动态创建(仅当项目在列表中实际可见时),因此上述方法不会返回容器对于当前不可见的项目。
在这种情况下,通常最好通过ItemContainerStyle
中的Background
在Setter
属性上定义绑定。
答案 2 :(得分:3)
使用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项而不是使用数据模板。您可能必须向视图模型添加一些属性以用于显示目的。
答案 3 :(得分:1)
假设ListBox中的项目类型为 Foo ,并且在ListBox中,您将为每个Foo项目显示 Foo.ItemInfo ,最后让我们说有一个属性称为状态,用于确定每个 Foo.ItemInfo 在ListBox中相对于背景,前景,字体样式和工具提示文本的显示方式。根据这些要求,在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>
接下来,在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
答案 4 :(得分:1)
经过一些谷歌搜索后,我发现了自己的解决方案 我正在使用Listview.ItemsSource和作为源我使用List 然后我可以在List中设置指定ListViewItem的背景,只刷新listview。
XAML:
*** Error renewing session: Optional(Error Domain=com.spotify.auth Code=400 "No refresh token available in the session!" UserInfo={NSLocalizedDescription=No refresh token available in the session!})
使用带灰色背景的项目填充ListView:
<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>
为行更改颜色创建方法:
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; }
}
并使用它:
private void ChangeRowColor(int RowIndex,SolidColorBrush NewBackground)
{
ITEMS[RowIndex].Background = NewBackground;
listView.Items.Refresh();
}
答案 5 :(得分:0)
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; }
}