Wpf Combobox in Master/Detail MVVM
I have MVVM master /details like this:
<Window.Resources>
<DataTemplate DataType="{x:Type model:EveryDay}">
<views:EveryDayView/>
</DataTemplate&g开发者_如何转开发t;
<DataTemplate DataType="{x:Type model:EveryMonth}">
<views:EveryMonthView/>
</DataTemplate>
</Window.Resources>
<Grid>
<ListBox Margin="12,24,0,35" Name="schedules"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Path=Elements}"
SelectedItem="{Binding Path=CurrentElement}"
DisplayMemberPath="Name" HorizontalAlignment="Left" Width="120"/>
<ContentControl Margin="168,86,32,35" Name="contentControl1"
Content="{Binding Path=CurrentElement.Schedule}" />
<ComboBox Height="23" Margin="188,24,51,0" Name="comboBox1"
VerticalAlignment="Top"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Path=Schedules}"
SelectedItem="{Binding Path=CurrentElement.Schedule}"
DisplayMemberPath="Name"
SelectedValuePath="ID"
SelectedValue="{Binding Path=CurrentElement.Schedule.ID}"/>
</Grid>
This Window has DataContext class:
public class MainViewModel : INotifyPropertyChanged {
public MainViewModel() {
elements.Add(new Element("first", new EveryDay("First EveryDay object")));
elements.Add(new Element("second", new EveryMonth("Every Month object")));
elements.Add(new Element("third", new EveryDay("Second EveryDay object")));
schedules.Add(new EveryDay());
schedules.Add(new EveryMonth());
}
private ObservableCollection<ScheduleBase> _schedules = new
ObservableCollection<ScheduleBase>();
public ObservableCollection<ScheduleBase> Schedules {
get {
return _schedules;
}
set {
schedules = value;
this.OnPropertyChanged("Schedules");
}
}
private Element _currentElement = null;
public Element CurrentElement {
get {
return this._currentElement;
}
set {
this._currentElement = value;
this.OnPropertyChanged("CurrentElement");
}
}
private ObservableCollection<Element> _elements = new
ObservableCollection<Element>();
public ObservableCollection<Element> Elements {
get {
return _elements;
}
set {
elements = value;
this.OnPropertyChanged("Elements");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName) {
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
One of Views:
<UserControl x:Class="Views.EveryDayView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid >
<GroupBox Header="Every Day Data" Name="groupBox1" VerticalAlignment="Top">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBox Name="textBox2" Text="{Binding Path=AnyDayData}" />
</Grid>
</GroupBox>
</Grid>
My SelectedItem in ComboBox doesn't works correctly. Are there any visible errors in my code?
What I usually do is bind the items of an ItemsControl
to an ICollectionView
(usually ListCollectionView) instead of directly to a collection; I think that's what the ItemsControl
does by default anyway (creates a default ICollectionView
), but I might be wrong.
Anyway, this allows you to work with the CurrentItem
property of the ICollectionView
, which is automatically synchronized with the selected item in an ItemsControl
(if the IsSynchronizedWithCurrentItem
property of the control is true or null/default). Then, when you need the current item in the ViewModel, you can use that instead. You can also set the selected item by using the MoveCurrentTo...
methods on the ICollectionView.
But as I re-read the question I realize you may have another problem altogether; you have a collection of 'default' items and need a way to match them to specific instances. It would however be a bad idea to override the equality operators of the objects to consider them always equal if they are of the same type, since that has the potential to make other code very confusing. I would consider extracting the type information into an enum, and put a read-only property on each object returning one of the enum values. Then you can bind the items to a collection of the enum values, and the selected item to the enum property of each object.
Let me know if you need an example, I may have made a mess of the explanation :)
精彩评论