Home > other >  Displaying an Image and Text in a ComboBox in a DataGridComboBoxColumn
Displaying an Image and Text in a ComboBox in a DataGridComboBoxColumn

Time:01-25

I have a DataGrid with a column that is a DataGridComboBoxColumn. For the items in those combo boxes I need to display an image and some text. Below is what I was able to do. But the initial binding isn't working. And once I select an item in the combobox the images all disappear in all the comboboxes.

Is what I am doing on the right path to getting this to work with some sort of trigger or binding I am missing? Or is there a better way to display both an image and text in a combobox in a datagrid?

<DataGridComboBoxColumn Header="Status" SelectedValueBinding="{Binding Status}" SelectedItemBinding="{Binding Status}" SelectedValuePath="Tag" xmlns:s="clr-namespace:System;assembly=mscorlib"
                                                    >
                                <DataGridComboBoxColumn.ItemsSource>
                                    <x:Array Type="{x:Type StackPanel}">
                                        <StackPanel Orientation="Horizontal">
                                            <Image Source="{DynamicResource DispatchedImage}">
                                              
                                            </Image>
                                            <TextBlock Text="DISP"/>
                                            
                                            <StackPanel.Tag>
                                                <s:String>"1"</s:String>
                                            </StackPanel.Tag>
                                        </StackPanel>

                                        <StackPanel Orientation="Horizontal">
                                            <Image Source="{DynamicResource ConfirmedImage}">
                                            </Image>
                                            <TextBlock Text="CONF"/>
                                            <StackPanel.Tag>
                                                <s:String>"2"</s:String>
                                            </StackPanel.Tag>
                                        </StackPanel>

                                        <StackPanel Orientation="Horizontal">
                                            <Image Source="{DynamicResource PickedUpImage}">
                                                
                                            </Image>
                                            <TextBlock Text="P/U"/>
                                            <StackPanel.Tag>
                                                <s:String>"3"</s:String>
                                            </StackPanel.Tag>
                                        </StackPanel>

                                        <StackPanel Orientation="Horizontal">
                                            <Image Source="{DynamicResource DeliveredImage}">
                                           
                                            </Image>
                                            <TextBlock Text="DEL"/>
                                            <StackPanel.Tag>
                                                <s:String>"4"</s:String>
                                            </StackPanel.Tag>
                                        </StackPanel>
                                    </x:Array>
                                </DataGridComboBoxColumn.ItemsSource>
                            </DataGridComboBoxColumn>

CodePudding user response:

You should bind the ItemsSource of the ComboBox to an IEnumerable<T> where T is a type that has a property for the display value and the id value:

public class CustomerComboBoxItem
{
    public string Name { get; set; }
    public int Value { get; set; }
}

Add the following property to your view model:

public CustomerComboBoxItem[] Items { get; } = new CustomerComboBoxItem[]
{
    new CustomerComboBoxItem(){ Name ="DISP", Value = 1 },
    new CustomerComboBoxItem(){ Name ="CONF", Value = 2 },
    new CustomerComboBoxItem(){ Name ="P/U", Value = 3 },
    new CustomerComboBoxItem(){ Name ="DEL", Value = 4 }
};

...and use an ItemTemplate:

<DataGrid ...>
    <DataGrid.Resources>
        <DataTemplate x:Key="template">
            <StackPanel Orientation="Horizontal">
                <Image>
                    <Image.Style>
                        <Style TargetType="Image">
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding Text}" Value="DISP">
                                    <Setter Property="Source" Value="{DynamicResource DispatchedImage}" />
                                </DataTrigger>
                                <DataTrigger Binding="{Binding Text}" Value="CONF">
                                    <Setter Property="Source" Value="{DynamicResource ConfirmedImage}" />
                                </DataTrigger>
                                <DataTrigger Binding="{Binding Text}" Value="P/U">
                                    <Setter Property="Source" Value="{DynamicResource PickedUpImage}" />
                                </DataTrigger>
                                <DataTrigger Binding="{Binding Text}" Value="DEL">
                                    <Setter Property="Source" Value="{DynamicResource DeliveredImage}" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </Image.Style>
                </Image>
                <TextBlock Text="{Binding Name}"/>
            </StackPanel>
        </DataTemplate>
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridComboBoxColumn Header="Status"
                                SelectedValueBinding="{Binding Status}" 
                                SelectedValuePath="Id">
            <DataGridComboBoxColumn.ElementStyle>
                <Style TargetType="{x:Type ComboBox}">
                    <Setter Property="ItemsSource" Value="{Binding Path=DataContext.Items, RelativeSource={RelativeSource AncestorType=DataGrid}}" />
                    <Setter Property="ItemTemplate" Value="{StaticResource template}" />
                </Style>
            </DataGridComboBoxColumn.ElementStyle>
            <DataGridComboBoxColumn.EditingElementStyle>
                <Style TargetType="{x:Type ComboBox}">
                    <Setter Property="ItemsSource" Value="{Binding Path=DataContext.Items, RelativeSource={RelativeSource AncestorType=DataGrid}}" />
                    <Setter Property="ItemTemplate" Value="{StaticResource template}" />
                </Style>
            </DataGridComboBoxColumn.EditingElementStyle>
        </DataGridComboBoxColumn>
        ...
    </DataGrid.Columns>
</DataGrid>

See the section on data templating in the docs for more information.

  • Related