Я использую mvvm для разработки приложения sl4 службы RIA, и мне, кажется, что-то не хватает.
MVVM и привязка данных хорошо работают, когда ваши данные поступают в ожидаемом формате для редактирования или когда ваши объекты данных «соответствуют представлению» (сетки, списки и т. Д.). Но что происходит, когда ваши данные на самом деле не отображаются напрямую?
Мой пример
Допустим, у меня есть таблица продуктов, она определяет продукт, его цену и параметры. И у меня есть таблица продуктов с подпиской, которая будет связывать продукт и клиента, а также иметь данные о том, когда заканчивается подписка и т. Д.
Итак, когда я начал работать над своим представлением для «списка покупок», я сделал следующее:
<ListBox x:Name="ShopList" Grid.Row="0" ItemsSource="{Binding Products}">
<DataTemplate>
<StackPanel Orientation="Horizontal">
<sdk:Label Content="{Binding ModuleName}" />
<sdk:Label Content="{Binding DateStart, Converter={StaticResource gridDateFormatter}}" />
<sdk:Label Content="{Binding DateEnd, Converter={StaticResource gridDateFormatter}}" />
<telerik:RadMaskedTextBox MaskedText="{Binding UnitsToBuy}" />
<sdk:Label Content="{Binding UnitStep}" />
<sdk:Label Content="{Binding TotalPrice}" />
</StackPanel>
</DataTemplate>
</ListBox>
Итак, я подумал, что я свяжу ItemsSource с коллекцией Observable на моей ViewModel
public ObservableCollection<Product> Products
Но теперь у меня проблема: UnitsToBuy не входит в состав продукта и не принадлежит продукту. Я изо всех сил пытаюсь найти чистый способ справиться с подобными сценариями. Предположим, у меня может быть любое количество элементов в этом списке.
Спасибо.
3 ответа
Я думаю, то, о чем вы спрашиваете, сводится к тому, что представлению нужна модель представления с большим количеством свойств, а не простая модель. Почему бы не иметь что-то подобное. Очевидно, что приведенные ниже классы должны реализовывать INotifyPropertyChanged.
public class CartItem
{
public Product Product {get;set;}
public int UnitsToBuy {get;set;}
public int UnitsStep {get;set;}
public decimal TotalPrice
{
get { return Product.Price * UnitsToBuy;}
}
//more properties can be added if needed
}
public class ShoppingCartViewModel
{
public ObservableCollection<CartItem> Products {get;set;}
}
А затем в xaml вам действительно не нужно вносить какие-либо изменения.
Я бы создал новый класс Model, который будет содержать все, что вам нужно, из Product и SubscribedProduct. Затем вы можете создать своего рода Mapper, который преобразует модель, более ориентированную на представление, в ваши модели, ориентированные на данные (Product и SubscribedProduct).
Я всегда строю свои представления специально для модели или группы моделей. Благодаря этому я знаю, каких свойств ожидать, а каких может не хватать.
Если я знаю, что свойство может отсутствовать, я напишу DataTrigger
, чтобы изменить представление на основе данных
Например, если бы у меня было представление, которое должно было отображаться Products
и SubscribedProducts
, я мог бы использовать DataTrigger
, чтобы определить, какой DataTemplate отображать.
<Style TargetType="ListBoxItem">
<Setter Property="Template" Value="{StaticResource DefaultProductTemplate}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Converter={StaticResource ObjectToTypeConverter}}" Value="{x:Type local:SubscribedProductModel}">
<Setter Property="Template" Value="{StaticResource SubscribedProductTemplate}" />
</DataTrigger>
</Style.Triggers>
</Style>
Похожие вопросы
Новые вопросы
xaml
Расширяемый язык разметки приложений (XAML) - это декларативный язык на основе XML, используемый для инициализации структурированных значений и объектов в различных средах. Когда вопрос касается использования XAML с конкретной платформой, следует также предоставить тег для этой платформы, например, [wpf] (Windows Presentation Foundation), [silverlight], [windows-phone], [windows-store-apps] (приложения магазина Windows 8), [win-universal-app], [xamarin.forms] или [workflow- Фонд]