каждый.
Преамбула.
Давайте посмотрим на эту типичную ситуацию. Вот 3-х уровневое приложение:
- Клиент WPF (или Silverlight, это не имеет значения), построенный на MVVM;
- Служба WCF (сервер приложений);
- некоторые СУБД в качестве хранилища.
Вот простая модель домена "элементы порядка заказа":
[DataContract(IsReference = true)]
public class Order : INotifyPropertyChanged
{
[DataMember]
public Int32 Id { ... }
[DataMember]
public Decimal Total { ... }
[DataMember]
public Decimal Discount { ... }
[DataMember]
public ObservableCollection<OrderItem> Items { ... }
}
[DataContract(IsReference = true)]
public class OrderItem : INotifyPropertyChanged
{
[DataMember]
public Int32 Id { ... }
[DataMember]
public String Name { ... }
[DataMember]
public Decimal Price { ... }
[DataMember]
public Decimal Quantity { ... }
[DataMember]
public Order Order { ... }
[DataMember]
public Int32 OrderId { ... }
}
Свойства Order.Id и OrderItem.Id - это свойства идентичности.
Свойства Order.Total и Order.Discount рассчитываются свойствами.
Идентификационные и вычисляемые свойства не могут быть установлены на стороне клиента - они должны быть установлены на сервере, их значения зависят от логики сервера. Кроме того, сервер приложений может добавлять в заказ новые товары (например, подарки) или изменять количество существующих товаров (в зависимости от состояния товара).
На стороне клиента эти модели заключены в модели соответствующих представлений:
public class OrderVM : INotifyPropertyChanged
{
private Order model;
public OrderVM(Order model)
{
this.model = model;
...
}
public Int32 Id { ... }
public Decimal Total { ... }
public Decimal Discount { ... }
public ObservableCollection<OrderItemVM> Items { ... }
// ...
}
public class OrderItemVM : INotifyPropertyChanged
{
public OrderItemVM(OrderItem model)
{
...
}
public Int32 Id { ... }
public String Name { ... }
public Decimal Price { ... }
public Decimal Quantity { ... }
// ...
}
Классы модели реализуют INPC, поэтому, если модель была изменена вне пользовательского интерфейса, модель представления отразит эти изменения.
Сервер приложений - это служба WCF. Вот это контракт:
[ServiceContract(...)]
public interface OrderService
{
[OperationContract(...)]
Order SaveOrder(Order order);
}
Что делает OrderService.SaveOrder: он получает заказ, получает идентификационные данные и рассчитанные свойства, изменяет заказ (добавляет или изменяет элементы) и возвращает тот же заказ обратно клиенту.
OrderVM имеет команду «Применить». Представление, отображающее OrderVM, имеет кнопку, которая привязана к OrderVM.Apply.
OrderVM.Apply должен вызвать OrderService.SaveOrder:
void ApplyExecute()
{
var savedOrder = ordersService.SaveOrder(model);
}
Вопрос.
С точки зрения CLR, исходный порядок (поле OrderVM.order) и saveOrder - это разные объекты.
Мне нужно отразить изменения, которые теперь присутствуют в saveOrder, поэтому они должны отображаться пользователю.
Есть ли общие подходы или лучшие практики, как это сделать?
Пожалуйста, примите во внимание, что:
- команда «Применить», а не «Сохранить и закрыть»: пользователь должен оставаться в том же виде в том же порядке;
- это простая модель, реальные модели будут более сложными.
Спасибо.