Reputation: 310
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'
Upvotes: 1
Views: 3675
Reputation: 132558
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.
Upvotes: 5