Прежде всего, я - Java-разработчик, в настоящее время помогаю с проектом на C #, так что помните об этом, отвечая.
У меня следующий сценарий.У меня есть таблица данных с записями, и когда я дважды щелкаю, я открываю новое окно (диалог) с некоторыми полями и кнопкой сохранения и отмены.Я хочу, чтобы кнопка отмены отменила все изменения, сделанные в диалоговом окне.
Я бы сказал, что это очень распространенный сценарий, но мне нужно найти один единственный ответ на stackoverflow, который действительно работает и не требуетГазиллион строк стандартного кода.Я не собираюсь вставлять сюда весь свой проект и постараюсь сделать доступным соответствующий код
Galaxy и SelectedJob - это простые JSON-объекты, которые сериализуемы и не имеют ничего, кроме методов получения и установки.пример.Job.cs
using System;
using System.Collections.Generic;
namespace GalaxyCreator.Model.Json
{
[Serializable]
public class Job
{
public String Id { get; set; }
public String Name { get; set; }
public Boolean StartActive { get; set; }
public Boolean Disabled { get; set; }
public Boolean Rebuild { get; set; }
public Boolean Commandeerable { get; set; }
public Boolean Subordinate { get; set; }
public bool Buildatshipyard { get; set; } = true;
public JobLocation JobLocation { get; set; }
public JobCategory JobCategory { get; set; }
public JobQuota JobQuota { get; set; }
public IList<JobOrder> Orders { get; set; }
public String Basket { get; set; }
public String Encounters { get; set; }
public String Time { get; set; }
public Ship Ship { get; set; }
public IList<String> Subordinates { get; set; }
}
}
моя модель представления формы сетки данных.
using System.Windows;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaxyCreator.Dialogs.DialogFacade;
using GalaxyCreator.Model.Json;
namespace GalaxyCreator.ViewModel
{
class JobEditorViewModel : ViewModelBase
{
private IDialogFacade dialogFacade = null;
private RelayCommand<object> _jobEditorDetailClickedCommand;
public Galaxy Galaxy { get; set; }
public Job SelectedJob { get; set; }
public JobEditorViewModel(Galaxy Galaxy)
{
this.Galaxy = Galaxy;
this.dialogFacade = new DialogFacade();
}
public RelayCommand<object> JobEditorClickedCommand
{
get
{
if (_jobEditorDetailClickedCommand == null)
{
_jobEditorDetailClickedCommand = new RelayCommand<object>((param) => JobEditorClicked(param));
}
return _jobEditorDetailClickedCommand;
}
}
private void JobEditorClicked(object param)
{
Dialogs.DialogService.DialogResult result = this.dialogFacade.ShowJobEditorDetail("Job Editor Detail", param as Window, this.SelectedJob);
}
}
}
Представление для этой модели представления
<UserControl x:Class="GalaxyCreator.View.JobEditorView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:GalaxyCreator.View"
xmlns:model="clr-namespace:GalaxyCreator.Model.JobEditor"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd ="http://www.galasoft.ch/mvvmlight"
mc:Ignorable="d"
d:DesignHeight="1000" d:DesignWidth="1500">
<Grid>
<Border BorderBrush="Black" BorderThickness="1" Padding="5">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" Width="Auto">
<Label Content="Job Editor" FontSize="14" HorizontalContentAlignment="Center" Width="Auto"/>
<DataGrid x:Name="JobDataGrid"
ItemsSource="{Binding Path=Galaxy.Jobs}"
SelectedItem="{Binding Path=SelectedJob, Mode=TwoWay}"
AutoGenerateColumns="False" ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Auto" Height="500">
<DataGrid.Columns>
<DataGridTextColumn x:Name="JobId" Binding="{Binding Id}" Header="Id" IsReadOnly="True" />
<DataGridTextColumn x:Name="JobName" Binding="{Binding Name}" Header="Name" IsReadOnly="True" />
</DataGrid.Columns>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<cmd:EventToCommand Command="{Binding Path=JobEditorClickedCommand, Mode=OneWay}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
</StackPanel>
</Border>
</Grid>
</UserControl>
Ниже приведено несколько классов, которые откроют диалог и сделают несколько шаблонов, чтобы получить ответ из диалога и т. Д. ОниНе важно, я надеюсь на этот вопрос, поэтому я опускаю их и перехожу прямо к viewmodel диалоговой формы.Я читал кучу о шаблоне сувенира и держал где-то глубокий клон оригинального объекта и после отмены положил его обратно.Это звучало для меня как самое чистое решение из доступных.Кажется, есть еще дюжина таких явных, как updatemode или что-то в этом роде ... и затем обычно следуют 10000 строк о том, почему это не поддерживается с MVVM
using GalaSoft.MvvmLight.Command;
using GalaxyCreator.Dialogs.DialogService;
using GalaxyCreator.Model.Json;
using System.Windows;
namespace GalaxyCreator.Dialogs.JobEditor
{
class JobEditorDetailViewModel : DialogViewModelBase
{
private JobEditorDetailMemento memento;
public Job Job { get; set; }
private RelayCommand<object> _saveCommand = null;
public RelayCommand<object> SaveCommand
{
get { return _saveCommand; }
set { _saveCommand = value; }
}
private RelayCommand<object> _cancelCommand = null;
public RelayCommand<object> CancelCommand
{
get { return _cancelCommand; }
set { _cancelCommand = value; }
}
private JobOrder _selectedOrder;
public JobOrder SelectedOrder
{
get { return _selectedOrder; }
set
{
if (_selectedOrder == value)
return;
_selectedOrder = value;
RaisePropertyChanged("SelectedOrder");
}
}
public JobEditorDetailViewModel(string message, Job job) : base(message)
{
this.memento = new JobEditorDetailMemento(job);
this.Job = job;
this._saveCommand = new RelayCommand<object>((parent) => OnSaveClicked(parent));
this._cancelCommand = new RelayCommand<object>((parent) => OnCancelClicked(parent));
}
private void OnSaveClicked(object parameter)
{
this.CloseDialogWithResult(parameter as Window, DialogResult.Yes);
}
private void OnCancelClicked(object parameter)
{
this.Job.Id = memento.Job.Id;
this.CloseDialogWithResult(parameter as Window, DialogResult.No);
}
}
}
Это сокращенный код xaml для этого подробного представления
<UserControl x:Class="GalaxyCreator.Dialogs.JobEditor.JobEditorDetailView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:GalaxyCreator.Dialogs.JobEditor"
xmlns:model="clr-namespace:GalaxyCreator.Model.Json"
xmlns:util="clr-namespace:GalaxyCreator.Util"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
mc:Ignorable="d" d:DesignWidth="600">
<Grid Margin="4">
<Label Content="Id" />
<TextBox Text="{Binding Path=Job.Id, Mode=TwoWay, ValidatesOnDataErrors=True, ValidatesOnNotifyDataErrors=True, ValidatesOnExceptions=True}" />
<Label Content="Name" Grid.Column="2" HorizontalAlignment="Left" VerticalAlignment="Center" />
<TextBox Text="{Binding Path=Job.Name, Mode=TwoWay, ValidatesOnDataErrors=True, ValidatesOnNotifyDataErrors=True, ValidatesOnExceptions=True}" Grid.Column="3" x:Name="name" />
<Button Name="btnSubmit" Content="Save"
Command="{Binding SaveCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}" Margin="0,0,0,5"/>
<Button Name="btnCancel" Content="Cancel"
Command="{Binding CancelCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}" />
</StackPanel>
</Grid>
</UserControl>
Видите, дело в том, что это действительно работает до определенной степени.Как видите, я тестирую только со свойством id.Когда я нажимаю «Отмена», диалоговое окно закрывается и в памяти свойство изменяется.Если дважды щелкнуть ту же строку в моей сетке данных, откроется диалоговое окно со старым значением.ОДНАКО ... свойство на сетке данных изменилось.Таким образом, в таблице данных вы видите мой новый напечатанный идентификатор, а в памяти он содержит старый.Мне нужен способ сообщить о том, что моя сетка данных эй ... пожалуйста, сделайте обновление, свойство изменилось.
Итак, большой вопрос:
- Могу ли я сойти с рук в этом?вероятно, взломать, а не очистить MVVM (и, честно говоря, после всех этих часов, я начинаю больше не беспокоиться)
- есть ли способ дать сигнал сетке данных "отрендерить" еще раз с помощьюновые данные в памяти