在WPF代码隐藏中,如何为每个单独的ListBoxItem设置背景色,其中颜色基于项目本身?

在WPF代码隐藏中,如何为每个单独的ListBoxItem设置背景色,其中颜色基于项目本身?,wpf,colors,background,code-behind,listboxitem,Wpf,Colors,Background,Code Behind,Listboxitem,我的最终目标是让一个列表框显示一个颜色列表,其中背景色的值就是颜色本身。最后,这个ListBox将加载以前保存的颜色集合,但现在我只是想让它使用虚拟数据——我使用System.Windows.Media.colors中的颜色填充的字典(,其中string是友好的名称,Color是一个自定义类,它只包含颜色的红色、绿色、蓝色和十六进制值)。它是这样设置的,因为用户存储的颜色最终只有一个名称(键)和RGB/Hex值 通过设置ItemsSource到App.SavedColors.Keys(其中Sav

我的最终目标是让一个
列表框
显示一个颜色列表,其中背景色的值就是颜色本身。最后,这个
ListBox
将加载以前保存的颜色集合,但现在我只是想让它使用虚拟数据——我使用
System.Windows.Media.colors
中的颜色填充的字典(
,其中
string
是友好的名称,
Color
是一个自定义类,它只包含颜色的
红色
绿色
蓝色
十六进制
值)。它是这样设置的,因为用户存储的颜色最终只有一个名称(键)和RGB/Hex值

通过设置
ItemsSource
App.SavedColors.Keys
(其中
SavedColors
是前面提到的字典),我可以在
列表框中显示颜色名称。我找到了一些答案,可以解释如果你知道你想要什么颜色(即如果“严重性”等于1,则为“绿色”或其他值),如何基于属性进行绑定,但对于绑定颜色也没有任何帮助

使用我在研究这一问题时发现的解决方案,我能够找出如何使它几乎正常工作。但这段代码似乎只是根据最后一个项目的颜色为所有项目的背景上色,所以我想象这只是在每次创建新行时更改整体背景色。如何保持每次迭代从覆盖以前的背景

到目前为止,我能使用的最接近的代码是:

//Bind the saved colors.
ListBox_SavedColors.ItemsSource = App.SavedColors.Keys;

//Color the backgrounds.
for (int i = 0; i < ListBox_SavedColors.Items.Count; i++)
{
    //Create the blank style.
    Style styleBackground = new System.Windows.Style();
    styleBackground.TargetType = typeof(ListBoxItem);

    //Get the color and store it in a brush.
    Color color = App.SavedColors[ListBox_SavedColors.Items[i].ToString()];
    SolidColorBrush backgroundBrush = new SolidColorBrush();
    backgroundBrush.Color = System.Windows.Media.Color.FromRgb(color.Red, color.Green, color.Blue);

    //Create a background setter and add the brush to it.
    styleBackground.Setters.Add(new Setter
    {
        Property = ListBoxItem.BackgroundProperty,
        Value = backgroundBrush
    });

    ListBox_SavedColors.ItemContainerStyle = styleBackground;
}
//绑定保存的颜色。
列表框_SavedColors.ItemsSource=App.SavedColors.Keys;
//给背景上色。
对于(int i=0;i
代码的问题在于,您分配了影响所有ListBoxItems的相同属性ItemsContainerStyle。因此,所有项目都将具有最后一个项目的颜色

您的代码应该直接指定项目的背景

for (int i = 0; i < ListBox_SavedColors.Items.Count; i++)
{
    //Get the color and store it in a brush.
    Color color = App.SavedColors[ListBox_SavedColors.Items[i].ToString()];
    SolidColorBrush backgroundBrush = new SolidColorBrush(color);

    ListBoxItem item = ListBox_SavedColors.ItemContainerGenerator.ContainerFromIndex(i) as ListBoxItem;
    item.Background = backgroundBrush;
}
XAML将如下所示:

<ListBox x:Name="MyList">
    <ListBox.Resources>
        <local:ListBoxItemColorConverter x:Key="ListBoxItemColorConverter"/>
    </ListBox.Resources>
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <Setter Property="Background" Value="{Binding Converter={StaticResource ListBoxItemColorConverter}}"/>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>


它必须是代码隐藏解决方案吗?在XAML中要容易得多。绝对不必。我只是对WPF/XAML非常陌生,所以我对C#代码隐藏更为熟悉/自信。如果你知道我的位置,我肯定愿意学习XAML。我肯定对这个转换器方法感兴趣。不管是什么老实说,更简单就是我想要的。尽管如此,谢谢你在我的代码中找到了错误!事情过于复杂的经典实例…在尝试了这段代码之后,我得到了
item
NullReferenceException
。似乎
ItemContainerGenerator
没有正确地抓取
ListBoxItem
给定索引。真的很奇怪。你在使用列表框吗?你使用虚拟化了吗?我在答案中添加了Convertor方法。是的,它肯定是一个列表框。除非它是默认值,否则我没有使用虚拟化(WPF/XAML的新功能,所以我甚至不知道这意味着什么)。至于Converter方法,我应该将这些东西存储在哪里?我将代码放在App.xaml.cs文件中,但当我尝试在列表框的xaml中访问它时,
local:ListBoxItemColorConverter
对我来说无法解决。我想像我这样的初学者可能会缺少更多的步骤。编辑:我查找了e我学到了如何添加本地名称空间。您将c代码放在一个单独的文件中。它是一个独立的类。然后在xaml中声明一个xmlns:local=…您将具有自动完成功能,并且需要选择转换器的名称空间。
<ListBox x:Name="MyList">
    <ListBox.Resources>
        <local:ListBoxItemColorConverter x:Key="ListBoxItemColorConverter"/>
    </ListBox.Resources>
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <Setter Property="Background" Value="{Binding Converter={StaticResource ListBoxItemColorConverter}}"/>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>