Thursday, May 5, 2011

WPF: ComboBoxItem background

Hi all,

I have a ComboBox based on XML file data:

<Root>
<Node Background="Yellow" Foreground="Cyan" Image="1.ico" Property="aaaa" Value="28" />
<Node Background="SlateBlue" Foreground="Black" Image="2.ico" Property="bbbb" Value="2.5" />
<Node Background="Teal" Foreground="Green" Image="3.ico" Property="cccc" Value="4.0" />
<Node Background="Yellow" Foreground="Red" Image="4.ico" Property="dddd" Value="0" /></Root>

So, in this case, I need to create a compound ComboBoxItem when each item has a suitable background.

I tried to do something like this:

    <UserControl.Resources>
    <DataTemplate DataType="Node">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" MinWidth="20"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="Auto" MinWidth="20"/>
            </Grid.ColumnDefinitions>
            <Border Background="{Binding XPath=@Background}" Grid.Column="0">
                <Image Source="{Binding XPath=@Image}" 
                       Width="16" 
                       Height="16" 
                       Margin="3" />
            </Border>
            <Border Background="{Binding XPath=@Background}" Grid.Column="1">
                <TextBlock Foreground="{Binding XPath=@Foreground}" 
                           Margin="3"
                           Text="{Binding XPath=@Property}" />
            </Border>
            <Border Background="{Binding XPath=@Background}" Grid.Column="2">
                <TextBlock Foreground="{Binding XPath=@Foreground}" 
                           Margin="3" 
                           FontWeight="Bold"
                           Text="{Binding XPath=@Value}" />
            </Border>
        </Grid>
    </DataTemplate>

    <XmlDataProvider x:Key="xmlNodeList" 
                     Source="/data/Combo.xml" 
                     XPath="/Root/Node"/>
</UserControl.Resources>

<ComboBox Name="myComboBox" 
          ItemsSource="{Binding Source={StaticResource xmlNodeList}}" 
          SelectedIndex="0" />

but it's not looks good :-(

What solution you recommend?

Thanks in advance!

From stackoverflow
  • One thing is that you forgot to indicate which template to use:

    <DataTemplate x:Key="Node">
          <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" MinWidth="20"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="Auto" MinWidth="20"/>
            </Grid.ColumnDefinitions>
            <Border Background="{Binding XPath=@Background}" Grid.Column="0">
                <Image Source="{Binding XPath=@Image}" 
                       Width="16" 
                       Height="16" 
                       Margin="3" />
            </Border>
            <Border Background="{Binding XPath=@Background}" Grid.Column="1">
                <TextBlock Foreground="{Binding XPath=@Foreground}" 
                           Margin="3"
                           Text="{Binding XPath=@Property}" />
            </Border>
            <Border Background="{Binding XPath=@Background}" Grid.Column="2">
                <TextBlock Foreground="{Binding XPath=@Foreground}" 
                           Margin="3" 
                           FontWeight="Bold"
                           Text="{Binding XPath=@Value}" />
            </Border>
        </Grid>
    </DataTemplate>
    

    And then your ComboBox:

    <ComboBox Name="myComboBox" 
              ItemsSource="{Binding Source={StaticResource xmlNodeList}}" 
              ItemTemplate="{StaticResource Node}"
              SelectedIndex="0" />
    

    The "dataType" system works with typed object, I'm not sure you can make it work with XML data. This will work.

    Update: Before you ask, you should also define a Style for the items so that they cove the width of the list, otherwise your columns are going to be uneven:

       <ComboBox Name="myComboBox"
                          ItemsSource="{Binding Source={StaticResource xmlNodeList}}"
                          ItemTemplate="{StaticResource Node}"
                          SelectedIndex="0">
                    <ComboBox.ItemContainerStyle>
                        <Style TargetType="{x:Type ComboBoxItem}">
                            <Setter Property="HorizontalContentAlignment"
                                    Value="Stretch" />
                        </Style>
                    </ComboBox.ItemContainerStyle>
                </ComboBox>
    

    This will stretch the individual items to cover the whole width of the list.

    : Hello Denis, Thank you for the response! I tried your suggestions, but: 1. ItemTemplate="{StaticResource Node}" generates runtime error: Cannot find resource named '{Node}' at InitializeComponent() method 2. Added style nothing has changed 3. One of problems that when mouse hover ComboboxItems, the highlight occurs under the Grid
    Denis Troller : note my remark that says you need to give a x:Key="Node" and not DataType="Node" attribute to your DataTemplate. That is the source of the error.
    Denis Troller : I updated my answer to include the full template, i's clearer that way.

0 comments:

Post a Comment