Question

I am trying to bind a property of my DataContext to the SelectedItem on a ComboBox like this:

<ComboBox x:Name="ElementSelector" 
          ItemsSource="{Binding Source={StaticResource Elements}}"
          DisplayMemberPath="ElementName"
          SelectedItem="{Binding ValueElement, Mode=TwoWay}">

where the Elements resource is a CollectionViewSource (don't know, whether this matters).

When everything is initialized, the property ValueElement of the DataContext is set to the first item in the CollectionViewSource. What I want, is to initialize it the other way around: I would like to set SelectedItem of the ComboBox to the value of the property or null if no matching item is contained.

How can this be done?

EDIT - Additional information:

The ComboBox is part of a DataTemplate:

<DataTemplate x:Key="ReferenceTemplate" 
              DataType="viewModels:ElementMetaReferenceViewModel">
   <StackPanel Orientation="Horizontal">
      <StackPanel.Resources>
         <ResourceDictionary>
            <views:ElementsForReferenceViewSource x:Key="Elements" 
                                                  Source="{Binding  DataContext.CurrentProject.Elements, ElementName=Root}" 
                                                  ReferenceToFilterFor="{Binding}"/>
         </ResourceDictionary>
      </StackPanel.Resources>

      <TextBlock Text="{Binding PropertyName}"/>
      <ComboBox x:Name="ElementSelector" 
                ItemsSource="{Binding Source={StaticResource Elements}}"
                DisplayMemberPath="ElementName" 
                SelectedItem=""{Binding ValueElement, Mode=TwoWay}" />

   </StackPanel>
</DataTemplate>

The ElementsForReferenceViewSource simply derives from CollectionViewSource and implements an additional DependencyProperty which is used for filtering.

The DataContext of the items in the CollectionViewSource look like this:

public class ElementMetaReferenceViewModel : ViewModelBase<ElementMetaReference, ElementMetaReferenceContext>
{
   ...
    private ElementMetaViewModel _valueElement;

    public ElementMetaViewModel ValueElement
    {
        get { return _valueElement; }
        set
        {
            if (value == null) return;
            _valueElement = value;
            Model.TargetElement = value.Model;
        }
    }

    ...
}
Was it helpful?

Solution

For people encountering the same issue

The above code works as expected. The solution was getting the stuff behind the scenes right. Make sure, that the instance of the ViewModel which is the value of the property you want to bind to is definitely contained in the CollectionViewSource.

In my case the issue was deserializing an object tree incorrectly, so objects were instantiated twice. Then for each object a distinct ViewModel was initialized and then obviously the value of the property was not contained in the list.

Remark

To check whether this is an issue in your case, you can try the following:

Override the ToString() methods of the ViewModels displayed in the ComboBox like this:

public override string ToString()
{
   return "VM"+ Model.GetHashCode().ToString();
}

Then you can easily compare the items in the source collection with the value on your property. Not the most professional way, but it did the job for me.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top