0

I have below WPF combobox:

<ComboBox x:Name="MyComboBox"
            Grid.Column="1"
            SelectionChanged="MyComboBox_SelectionChanged">
    <ComboBox.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel />
        </ItemsPanelTemplate>
    </ComboBox.ItemsPanel>

    <ComboBoxItem Name="cbiEmployeeManagerType">
        <StackPanel Orientation="Horizontal">
            <Image Source="/Resources/Manager.png" />
            <TextBlock Foreground="AliceBlue"
                        VerticalAlignment="Center">Manager</TextBlock>
        </StackPanel>
    </ComboBoxItem>
    <ComboBoxItem Name="cbiEmployeeEngineerType">
        <StackPanel Orientation="Horizontal">
            <Image Source="/Resources/Engineer.png" />
            <TextBlock Foreground="AliceBlue"
                        VerticalAlignment="Center">Engineer</TextBlock>
        </StackPanel>
    </ComboBoxItem>
</ComboBox>

First problem:

Within MyComboBox_SelectionChanged I know how to detect which item is currently selected in the combobox through MyComboBox.SelectedIndex but I do not know how to get the text that appears displayed and currently selected in the combobox. For example, If I select the second item in my combobox, I want to obtain "Engineer". How can I do it?

Second problem:

Also I would like to do the same as in combobox winforms in which you can display a member (DisplayMember property of combobox in winforms) and internally to associate it a member value (ValueMember property of combobox in winforms) which you can read when you selected the item within the combobox. For example suppose the following combox items with their associated values.

  • "Manager" : 1000A
  • "Engineer" : 1000B

So "Manager" and "Engineer" would be displayed in the combox and when I would select "Manager" I would obtain its associated value, that is, 1000A, the same for Engineer. Is it possible in WPF? If so how? I have read that it is possible using DisplayMemberPath and SelectedValuePath combobox properties but I do not know how to do it. Do I need to create a class and populate the combo from there and then using binding? Any piece of code will be highly appreciated.

UPDATE: For second problem finally I have done similar to what is explained here and here.

Astro
  • 367
  • 1
  • 3
  • 17
  • Two notes. 1. It doesn't seem to make any sense to have a VirtualizingStackPanel in a ComboBox. Remove the entire ComboBox.ItemsPanel. 2. You repeatedly add ComboBoxItems with a StackPanel with two child elements. That should be done by a DataTemplate in the ItemTemplate property of the ComboBox. Inside the DataTemplate you would bind to properties of the item type. The ItemsSource property of the ComboBox would be bound to a collection of this item type. See [Data Templating Overview](https://docs.microsoft.com/en-us/dotnet/framework/wpf/data/data-templating-overview) for how to start. – Clemens Jul 30 '17 at 09:08

1 Answers1

0

For the first problem you can access to TextBlock of ComboBoxItem by digging through the SelectionChangedEventArgs e of the SelectionChanged event with this kind of line of code:

private void MyComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    var selectedItem = e.AddedItems[0] as ComboBoxItem;
    var itemStackPanel = selectedItem.Contents as StackPanel;

    // Get the TextBlock object from 'itemStackPanel' object
    // TextBlock is with index 1 because it is defined second
    //  after Image inside the StackPanel in your XAML
    var textBlock = itemStackPanel.Children[1] as TextBlock;
    // This variable will hold 'Engineer' or 'Manager'
    var selectedText = textBlock.Text;

}

or you can use this short line that combines all the above code in one line: (the ?. is C# 6 feature to check for null in case something goes wrong)

var selectedText = (((e.AddedItems[0] as ComboBoxItem)?.Content as StackPanel)?.Children[1] as TextBlock)?.Text;
Redouane
  • 430
  • 2
  • 9