Изменить цвет фона строки ListView программно (wpf) - PullRequest
9 голосов
/ 30 мая 2011

У меня есть класс, который заполняет ListView, передавая список объектов.Класс использует отражение, чтобы увидеть свойства каждого объекта для генерации 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;                
}

, и я получаю эту ошибку:

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 имеет значение null после 12 итераций?

Работает только с отображаемыми элементами ....

Ответы [ 6 ]

10 голосов
/ 30 мая 2011

Вам нужно ввести ViewModels вместо уничтожения пользовательского интерфейса WPF. например Я мог бы создать его следующим образом

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 к этой коллекции и правильно соединить 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 значение Color. например чтобы настроить все элементы на PaleGreen

private void Button_Click(object sender, RoutedEventArgs e)
    {
        foreach (var item in Items)
            item.BackgroundColor = Colors.PaleGreen;
    }
4 голосов
/ 30 мая 2011

Вы можете использовать ItemContainerGenerator, например:

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

Однако по умолчанию ListView виртуализируется, это означает, что ListViewItems создаются по мере необходимости(только если элемент действительно виден в списке), поэтому вышеуказанные методы не будут возвращать контейнеры для элементов, которые в данный момент не видны.

В этом случае обычно предпочтительнее определить привязку для Background собственность через Setter в ItemContainerStyle.

3 голосов
/ 30 мая 2011

При использовании 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)
        {
            ...
        }
    }  
}

Не уверен, что это создаст какие-либо странные эффекты рисования (мерцание) или нет.

Другой вариант вместо построения спискаэлементы в коде для вас использовать шаблоны данных.Возможно, вам придется добавить несколько свойств к вашей модели представления для отображения.

1 голос
/ 06 марта 2017

После некоторого поиска в Google я нашел свое собственное решение Я использую Listview.ItemsSource и в качестве источника я использую список Затем я могу установить фон для указания ListViewItem в List и просто обновить представление списка.

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>

Заполнить 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();
    }

И используйте это:

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        ChangeRowColor(4, Brushes.Green);
    }
1 голос
/ 05 июля 2013

Предполагая, что элементы в вашем ListBox имеют тип Foo , и в ListBox вы будете отображать Foo.ItemInfo для каждого элемента Foo, и, наконец, скажем, есть свойство с именем Status , определяющий способ отображения каждого 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>

Затем добавьте следующее в свой файл MainWindow.xaml.cs (или как вы назвали сопроводительный файл XAML) в C #:

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

0 голосов
/ 21 июня 2018
  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; }
}

снимок экрана

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...