Поле со списком с источником элементов представления коллекции не обновляет элемент поля выбора при изменении модели

Извините за более ранний пространный пост. Вот мое краткое (!) Описание.

Я привязываю представление коллекции к полю со списком как itemsSource, а также привязываю его selectedvalue к свойству из моей модели представления. Я должен оставить IsSynchronizedWithCurrentItem = "False".

Я меняю список источников представления, а затем обновляю представление. Измененные (добавленные, удаленные, отредактированные) элементы правильно отображаются в списке элементов комбо. Но проблема в выбранном элементе. Когда я изменяю его свойство, которое также является путем отображаемого элемента комбо, измененное значение свойства не отражается обратно в поле выбора комбо. Если вы откроете раскрывающийся список со списком, он правильно отобразится в списке элементов, но не в поле выбора.

Теперь, если я изменю тег combobox на Listbox в моем XAML (сохраняя все атрибуты как есть), тогда, когда значение свойства displaymember выбранного элемента обновляется, изменения отражаются на выбранном элементе списка.

Почему эта проблема?

Просто к вашему сведению:

  1. Моя модель представления имеет свойства EmployeeCollectionView и SelectedEmployeeId, которые привязаны к комбинации как ItemsSource и SelectedValue, соответственно. Эта виртуальная машина реализует интерфейс INotifyPropertyChanged.

  2. Мой основной класс сотрудников (список которых является источником для EmployeeCollectionView) - это просто класс модели без INotifyPropertyChanged.

  3. DisplayMemberPath - это свойство «Имя» класса модели сотрудника. Я каким-то образом меняю это значение и ожидаю, что поле выбора со списком обновит значение.

  4. Я попытался обновить SelectedEmployeeId, установив для него 0 (где он правильно выбирает фиктивную запись сотрудника "- Select All -" из itemsSource) и старое выбранное значение обратно. Но бесполезно. Старое значение возвращает меня к старому лейблу. Однако в коллекции предметов есть последняя запись.

  5. Когда я делаю IsEditable = True combobox перед обновлением представления и после обновления я делаю IsEditable = False, тогда все работает правильно!

Но это патч, и в нем нет необходимости.

Спасибо

Винит Санкхе


person Vinit Sankhe    schedule 29.04.2010    source источник


Ответы (1)


Ваши пункты №2 и №3 объясняют, почему это не работает. Когда в ComboBox выбран элемент, он отображает в поле свойство Employee.Name. В № 2 вы заявляете, что Employee не реализует INotifyPropertyChanged, а в № 3 вы меняете имя и ожидаете его обновления в ComboBox. Но ComboBox не знает, что свойство изменилось, поэтому его отображаемое значение не изменится.

Я собрал очень простой пример, который продемонстрирует. Если вы закомментируете событие PropertyChanged, вы заметите, что нажатие кнопки больше не влияет на пользовательский интерфейс.

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        SizeToContent="WidthAndHeight">
    <StackPanel>
        <ComboBox ItemsSource="{Binding}" DisplayMemberPath="Name" SelectedIndex="0" Width="150" Height="25" />
        <Button Content="Change" Width="75" Height="25" Click="button_Click"/>
    </StackPanel>
</Window>

И код, стоящий за ...

public partial class MainWindow : Window
{

    private ObservableCollection<Thing> things;
    private Queue<string> words;

    public MainWindow()
    {

        // some dummy data
        string text = "Lorem ipsum dolor sit amet consetetur sadipscing elitr sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat sed diam voluptua";
        words = new Queue<string>(text.Split(' '));

        things = new ObservableCollection<Thing>();
        things.Add(new Thing { Name = words.Dequeue() });
        things.Add(new Thing { Name = words.Dequeue() });
        things.Add(new Thing { Name = words.Dequeue() });

        DataContext = things;

        InitializeComponent();

    }

    private void button_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        things[0].Name = words.Dequeue();
    }

}
person Josh    schedule 29.04.2010
comment
Привет, Джош, спасибо за ответ, но тогда почему это работает для ListBox. Выбранный элемент ListBox правильно показывает обновленное имя (без интерфейса INotify). Насколько мне известно, в MVVM базовым классам модели (в моем случае - классу сотрудников) не рекомендуется иметь INotifyPropertyChanged. только ViewModels реализуют этот интерфейс. - person Vinit Sankhe; 30.04.2010
comment
Не видя кода, мне трудно сказать, почему работает ListBox. Но ваше понимание MVVM не обязательно неверно, но MVVM все еще относительно новый, и на самом деле нет никаких жестких и быстрых правил. Дело в том, что в MVVM вы не должны открывать класс модели непосредственно в пользовательском интерфейсе, но каждый время от времени нарушает это правило. Но если вы хотите, чтобы изменения связанных членов отражались в пользовательском интерфейсе, вы должны реализовать INotifyPropertyChanged. - person Josh; 30.04.2010