Wpf Combobox в Мастер / Деталь MVVM - PullRequest
3 голосов
/ 21 марта 2010

У меня есть мастер / детали MVVM:

<Window.Resources>
<DataTemplate  DataType="{x:Type model:EveryDay}">
    <views:EveryDayView/>
</DataTemplate>

<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>

В этом окне есть класс DataContext:

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
}

Один из видов:

<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>

Мой SelectedItem в ComboBox не работает правильно.Есть ли видимые ошибки в моем коде?

1 Ответ

0 голосов
/ 26 августа 2010

Что я обычно делаю, это привязываю элементы ItemsControl к ICollectionView (обычно ListCollectionView), а не напрямую к коллекции; Я думаю, что это то, что ItemsControl делает по умолчанию (создает значение по умолчанию ICollectionView), но я могу ошибаться.

В любом случае, это позволяет вам работать со свойством CurrentItem ICollectionView, которое автоматически синхронизируется с выбранным элементом в ItemsControl (если свойство IsSynchronizedWithCurrentItem элемента управления имеет значение true или null / дефолт). Затем, когда вам нужен текущий элемент в ViewModel, вы можете использовать его вместо этого. Вы также можете установить выбранный элемент, используя методы MoveCurrentTo... в ICollectionView.

Но, перечитывая вопрос, я понимаю, что у вас может быть и другая проблема; у вас есть коллекция элементов по умолчанию, и вам нужен способ сопоставить их с конкретными экземплярами. Однако было бы плохой идеей переопределить операторы равенства объектов, чтобы считать их всегда равными, если они имеют один и тот же тип, поскольку это может сделать другой код очень запутанным. Я хотел бы рассмотреть возможность извлечения информации о типе в перечисление и поставить свойство только для чтения для каждого объекта, возвращающего одно из значений перечисления. Затем вы можете привязать элементы к коллекции значений перечисления, а выбранный элемент - к свойству перечисления каждого объекта.

Дайте мне знать, если вам нужен пример, я, возможно, напутал объяснение:)

...