Reputation: 39068
I've bound a text box's text and a combo box's selected item to my view model. The elements in the combo box are bound to a static property.
<TextBox x:Name="Texty"
Text="{Binding CurrentThing.Texty}" ... />
<ComboBox x:Name="Picky"
ItemsSource="{x:Static local:MainWindow.AllPickables}"
SelectedItem="{Binding CurrentThing.Picked}" ... />
It seems that the binding is in effect because the text box receives the correct content. The combo box gets it's values in the list correctly too. However, the issue is that the selection isn't being made.
At first I though that it had to do with the fact that some controllers have another default for Mode, so I tried explicitly setting it to two-way for the combo box. No difference in behavior as far I could see.
What can I be doing wrong. How to resolve it (or at least trouble-shoot)?
I've followed every hint from all I could find as the hints are more or less the same everywhere. Nothing worked, accept the approach of setting the selected index instead of the selected item. Sadly, I don't see how I could achieve that.
I've tried adding DisplayMemberPath, as suggested. That didn't work and the items of the combo box are not present anymore. I'm guessing that DisplayMemberPath refers to where to get stuff to itemize from whatever is referred to in ItemSource (and there's no Picked in there).
<ComboBox x:Name="Picky"
ItemsSource="{x:Static local:MainWindow.AllPickables}"
SelectedItem="{Binding CurrentOrder}"
DisplayMemberPath="Picked" ... />
View model assignment to the main window.
<Window.DataContext>
<local:Presenter/>
</Window.DataContext>
The view model of used (circumsized version regarding the components in question in order to be a minimal example).
public class Presenter : INotifyPropertyChanged
{
private ObservableCollection<Thing> _allThings;
private Thing _currentThing;
public Thing CurrentThing
{
get { return _currentThing; }
set { _currentThing = value; OnPropertyChanged(); }
}
public ListCollectionView AllThingsView { get; set; }
private IEnumerable<PickType> _allPickables;
public IEnumerable<PickType> AllPickables
{
get { return _allPickables; }
set { _allPickables = value; OnPropertyChanged(); }
}
public Presenter()
{
_allThings = new ObservableCollection<Thing>(DataAccessor.GetThings());
AllThingsView = new ListCollectionView(_allThings);
_allPickables = DataAccessor.GetPickables();
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] String name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
Main window's code behind (the parts that relate to used controls and events). I also have a grid view called ThingListing in my markup, which is bound to AllThingsView in my view model. When I click on a record in it, the event fired is supposed to update the value of CurrentThing and change the tab to the one where the bound controls are placed. Everything seems to get in the right places accept the selected items for combo boxes. I also have a convenience extension method Get. It does what you intuitively think it would (tested back and forth since forever).
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new Presenter();
}
private void ThingListing_OnMouseDoubleClick(Object sender, MouseButtonEventArgs eventArgs)
{
DataContext.Get<Presenter>().CurrentThing
= sender.Get<DataGrid>().CurrentItem.Get<Thing>();
Dispatcher.BeginInvoke((Action)(() => tabControl.SelectedIndex = 1));
}
}
Upvotes: 1
Views: 798
Reputation: 601
It looks like the comparison fails when the view model is being read. This likely happens because of incorrect/missing implementation of comparison methods. Try implementing Equals and GetHash and see if it works.
public override bool Equals(Object input)
{
return Id == ((Thing)input)?.Id;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
Upvotes: 1
Reputation: 9772
For a ComboBox
in WPF its essential to have SelectedItem
set to an object present in ItemsSource
in your case in IEnumerable<PickType> AllPickables
and in XAML ItemSource
must be positioned before SelectedItem
(as you already have it)
At the time the ComboBox
sees SelectedItem
it must be present in its Items
. This rule also applies at a later time i.e. when NotifyPropertyChanged
fires.
Further: CurrentThing
should have the same type PickType
public PickType CurrentThing { ... }
and CurrentThing
shoud point to one existing member in AllPickables
(or set to null for no selection).
Upvotes: 1