简体   繁体   中英

WPF databinding colored items in a combobox

I have read a couple of other articles, but none have been able to answer my combination of issues
I have a ComboBox in which i want to display items in different colors, this can be done by using a ComboBoxItem and settings its Background. My problem arises when i want to store my CategoryDTOs in different colors and later be able to extract them again. What i need to have displayed is just the color and the Name property of my CategoryDTOs. And i must then be able to get the CategoryDTO object from the SelectedItem property. I have attempted various solutions using ItemsSource, DisplayMemberPath and SelectedValuePath. But have only accomplished this 组合框的图片
As is seen it displays the colors, but only displays the Name of the selected CategoryDTO and i havent even tested if SelectedItem works correctly yet. Below i will put the code i use.

[Serializable]
public class CategoryDTO
{
    public string Name { get; set; }
    ...not important...
}


CategoryDTO[] categories = await _isd.GetCategoriesAsync();
comboBoxCategory.ItemsSource = categories.Select(c => new CategoryComboBoxItem(c)).ToList();
comboBoxCategory.DisplayMemberPath = "Name";
comboBoxCategory.SelectedValuePath = "Name";

public class CategoryComboBoxItem : ComboBoxItem
{
    public CategoryComboBoxItem(CategoryDTO category)
    {
        this.Background = new SolidColorBrush(category.Color);
        this.Content = category;
    }
}

I dont have anything special specified in the .xaml so i will leave that part out. Beyond this i would like to be able to set the SelectedItem using the Name property. I very much prefer the answers to be in code-behind, but if it is stupidly complicated .xaml only answers are just as fine. I dont have any experience with MVVM, i can assume it will be suggested. I will of course expand my knowledge on that matter as i delve deeper into WPF, but right now i just would like this to work.
This is not homework

EDIT: forgot to list errors i also get

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''.
BindingExpression:Path=HorizontalContentAlignment; DataItem=null; target element is 'CategoryComboBoxItem' (Name=''); target property is 'HorizontalContentAlignment' (type 'HorizontalAlignment') System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''.
BindingExpression:Path=VerticalContentAlignment; DataItem=null; target element is 'CategoryComboBoxItem' (Name=''); target property is 'VerticalContentAlignment' (type 'VerticalAlignment') System.Windows.Data Error: 26 : ItemTemplate and ItemTemplateSelector are ignored for items already of the ItemsControl's container type; Type='CategoryComboBoxItem'

To do this properly with WPF, I think you need a better understanding of the DataContext and how it works. I wrote a blog post just for linking on SE for this: What is this "DataContext" you speak of? . I'd highly recommend making sure you understand the DataContext before doing anything with WPF.

Your overall idea is you want to bind a ComboBox to a list of CategoryDTO items, and have the SelectedValue property be set to the Name .

<!-- create a ComboBox -->
<ComboBox x:Name="MyComboBox" SelectedValuePath="Name">
    <!-- Add a custom Style to the individual items in combobox -->
    <ComboBox.ItemContainerStyle>
        <!-- In custom style, bind background color -->
        <Style TargetType="{x:Type ComboBoxItem}">
           <Setter Property="Background" Value="{Binding Color}"/>
        </Style>
    </ComboBox.ItemContainerStyle>
</ComboBox>

You can either set the items for your ComboBox with a binding if your DataContext is set correctly

<ComboBox ItemsSource="{Binding CategoryList}" ..>

Or with code behind

MyComboBox.ItemsSource = CategoryList;

This will also sync up your ComboBox.SelectedItem with the selected CategoryDTO item in your list, so you can directly cast it to do something with it

CategoryDTO selected = (CategoryDTO)MyComboBox.SelectedItem;
DoSomethingWithSelected(selected);

or bind it so it's easy to use from the DataContext

<ComboBox SelectedItem="{Binding SelectedCategory}" ..>
// Can now use SelectedCategory directly
DoSomethingWithSelected(SelectedCategory);

Note: Depending on the data type of your .Color property, you may need to use a Converter to convert the .Color value to a SolidColorBrush for the .Background property. Should be plenty of examples of converters online, or just ask if you need help.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM