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

时间:2011-05-30 01:15:18

标签: c# wpf listview

我有一个通过传递对象列表来填充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;                
}

我收到此错误:

first try

我也试过这个:

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

}

我得到同样的错误:

enter image description here

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

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

6 个答案:

答案 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中的BackgroundSetter属性上定义绑定。

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

output screenshot

相关问题