Home > Enterprise >  How to choose an attribute of a child element as a SelectedValuePath in a ComboBox in WPF?
How to choose an attribute of a child element as a SelectedValuePath in a ComboBox in WPF?

Time:11-07

I have a ComboBox where I need to do this:

     <ComboBox x:Name="CitySelectComboBox" SelectedValuePath="Text">
            <b:Interaction.Triggers>
                <b:EventTrigger EventName="Loaded">
                    <b:InvokeCommandAction Command="{Binding DownloadWeatherCommand}"
                            CommandParameter="{Binding ElementName=CitySelectComboBox, Path=SelectedValue}" />
                </b:EventTrigger>
                <b:EventTrigger EventName="SelectionChanged">
                    <b:InvokeCommandAction Command="{Binding DownloadWeatherCommand}"
                            CommandParameter="{Binding ElementName=CitySelectComboBox, Path=SelectedValue}" />
                </b:EventTrigger>
            </b:Interaction.Triggers>

            <ComboBoxItem IsSelected="True">
                    <TextBlock Text="Praha"/>
            </ComboBoxItem>
            <ComboBoxItem>
                    <TextBlock Text="Brno"/>
            </ComboBoxItem>
    </ComboBox>

As you can see, I am trying to access the Text property of Textblock inside the ComboBoxItem. Just putting Text does not work as I get the following error:

BindingExpression path error: 'Text' property not found on 'object' ''ComboBoxItem' (Name='')'.

I need to find out how to specify the path to this property in the SelectedValuePath but no online resources have been helpful. The code otherwise works if I include the city names inside the ComboBoxItem as <ComboBoxItem Content="Praha"/>, but I need to take the name from the child element TextBlock.

CodePudding user response:

SelectedValuePath targets the SelectedItem, which is a ComboBoxItem in your case. ComboBoxItem does not have a Text property.

The TextBlock is assigned to the ComboBoxItem.Content property.
The valid property path is therefore "Content.Text":

<ComboBox SelectedValuePath="Content.Text">
  <ComboBoxItem IsSelected="True">
    <TextBlock Text="Praha" />
  </ComboBoxItem>
  <ComboBoxItem>
    <TextBlock Text="Brno" />
  </ComboBoxItem>
</ComboBox>

Because the ComboBoxItem (or ContentPresenter to be precise) will create a TextBlock implicitly in case the Content value is a string, defining a TextBlock explicitly is redundant.
Instead set the Content property directly. This reduces code and enhances the readability of your code:

<ComboBox SelectedValuePath="Content">
  <ComboBoxItem IsSelected="True"
                Content="Praha" />

  <!-- Alternative content property syntax -->
  <ComboBoxItem>Brno</ComboBoxItem>
</ComboBox>
  • Related