Проблема с реализацией MVVM: изменения в выбранном элементе распространяются на список, не хотят этого - PullRequest
4 голосов
/ 23 июня 2011

Итак, у меня возникла проблема, с которой, надеюсь, вы сможете помочь.

Я пишу приложение WPF, используя MVVM Light в качестве фреймворка.В этой ситуации у меня есть список элементов, и SelectedItem привязан к подробному представлению, где пользователь может редактировать элемент.В этом случае есть кнопка Сохранить для явного сохранения данных.

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

Я пытался реализовать реализацию клонирования, но как только я это сделал, система обмена сообщениями MVVM Light заканчивается циклом, в результате чего возникает исключение StackOverflowException из-за того, чтоЯ продолжаю клонировать объект.Кроме того, реализация клона уродлива.

Есть идеи о том, как я могу сделать это правильно?

РЕДАКТИРОВАТЬ:

Базовый XAML для представления списка:

    <DataGrid DataContext="{Binding SubJobTypes}"
              ItemsSource="{Binding}"
              SelectedItem="{Binding ElementName=Root, Path=DataContext.SelectedSubJobType, Mode=TwoWay}">
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Name}"/>
        </DataGrid.Columns>
    </DataGrid>

Базовый XAML для вида редактирования:

   <StackPanel>
        <StackPanel>
            <StackPanel Orientation="Horizontal" DataContext="{Binding Path=CurrentSubJobType}">
                <TextBlock Text="Name"/>
                <TextBox Text="{Binding Path=Name, Mode=TwoWay}" Width="150"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <Button Content="{Binding Path=SubmitCommandText, FallbackValue=Submit}" >
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="Click">
                            <GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding Path=SaveSubJobTypeCommand}"/>
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </Button>
                <Button Content="Cancel" >
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="Click">
                            <GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding Path=CancelCommand}"/>
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </Button>
                <Button Content="Delete">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="Click">
                            <GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding Path=DeleteCommand}"/>
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </Button>
            </StackPanel>
        </StackPanel>
    </StackPanel>

ViewModels являются стандартными, публиковать не будут

Ответы [ 3 ]

4 голосов
/ 23 июня 2011

Вместо отключения механизма привязки у вас должно быть две модели представления, одна для элементов списка и одна для подробного представления.После выбора элемента модель представления списка отправляет сообщение об измененном свойстве.Затем модель подробного представления загружает данные элементов или клонирует модель и инициализирует себя данными.Теперь модель подробного представления может изменить свой локальный экземпляр модели.

По окончании данные сохраняются в базе данных, и модель подробного представления отправляет сообщение об изменении элемента.Модель представления списка теперь получает сообщение и может использовать модель для изменения своей модели представления элемента, или вы можете перезагрузить модель элемента из базы данных и затем обновить модель представления элемента.

Таким образом, у вас нетвозиться с ручной записью значений в модель, и если вы только клонируете модель, у вас не должно возникнуть проблем с обменом сообщениями.

1 голос
/ 23 июня 2011

Может показаться, что вы (Двусторонняя) привязываете к одному и тому же объекту в ViewModel как в основном, так и в детальном представлении.

Возможные альтернативы:

  • создайте копию объекта
  • , создайте дополнительные параметры в вашей ViewModel, например, «EditName», и привяжите их к представлению редактирования вместо имени.Первоначально они будут установлены на то же значение, что и ваше свойство Name.При сохранении вы должны установить this.Name = this.EditName.При отмене вы должны установить this.EditName = this.Name.
0 голосов
/ 23 июня 2011

Я думаю, что вы, возможно, захотите отключить привязку данных «TwoWay» и записывать данные обратно в модель только тогда, когда пользователь нажимает кнопку «Отправить».

...