使用 MVVM 在模型外计算和查看列
Computing and viewing column outside model using MVVM
我需要使用 C# MVVM 解决以下问题。我正在使用以下模型。
我的一个 UserControl 得到了以下 ListBox 模板。
<ListBox ItemsSource="{Binding OrdersListViewViewModel.AllItems, Source={StaticResource Locator}}" SelectedItem="{Binding OrdersListViewViewModel.SelectedItem, Source={StaticResource Locator}}" Background="White">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" Margin="0 0 0 0" Height="Auto" Width="Auto" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,7,0,6" HorizontalAlignment="Left" Orientation="Horizontal">
<Image Width="25" Height="25" Margin="5 2 0 0" Source="{Binding OrdersListViewViewModel.OrderDeliveryStateImage, Mode=OneWay, Source={StaticResource Locator}}"/>
<TextBlock Margin="25,5,25,5" Text="{Binding OrdersListViewViewModel.AllItems/Customer.CustomerName, FallbackValue=N/A, Mode=OneWay, Source={StaticResource Locator}}" FontSize="20"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
该列表显示了从数据库加载的所有订单(客户名称)。我想用图片填充在 TextBlock 旁边的图像。如果订单下的所有orderitems都已发货(Delivered=1)应该用picture1,否则用picture2.
所以我要绑定 ObservableCollection<Order>
。模型是使用 entity framework(数据库优先)从 .tt 生成的,因此由于可能的数据库更新,将计算直接放入 Order.cs class 是个坏主意。
我的第一个想法是使用 MSSQL Computed 列,但我认为这不是一个好的方法(解决方案中可能有很多这样的情况)所以模型会庞大而复杂。
第二个想法是使用转换器,但它应该用于简单的任务,而不是用于计算逻辑(这是)。
第三个想法是将 ObservableCollection<Order>
更改为 ObservableCollection<Tuple<string,Order>>
并以某种方式将其绑定到视图但是......你知道,这是个坏主意。
所以我的问题很简单。我如何使用 MVVM 最佳实践解决这个问题(在哪里放置计算逻辑)。
谢谢。
经过谷歌搜索,我决定创建此解决方案。也许它会对某人有所帮助。
首先,我创建了部分 class 订单实体以分隔文件,因此当 entity framework 更新订单实体时,它不会覆盖我的自定义。
然后我创建了自定义 属性 来确定订单是否已交付。所以计算逻辑还是停留在模型上。
public partial class Order
{
public bool IsOrderDelivered
{
get
{
int orderDelivered = 1;
foreach (var orderItem in this.OrderItems)
{
orderDelivered = orderDelivered * orderItem.Delivered;
}
return orderDelivered == 1 ? true : false;
}
}
}
然后我创建了转换器,它只是将布尔值转换为文本,这就是它存在的原因,并且使用正确。
public class OrderStatusToImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (bool)value == true ? @"Skins\approved.png" : @"Skins\denied.png";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
并在部分 class 中与转换器一起在我的新 属性 上创建了数据绑定。
<StackPanel Margin="0,7,0,6" HorizontalAlignment="Left" Orientation="Horizontal">
<Image Width="25" Height="25" Margin="5 2 0 0" Source="{Binding IsOrderDelivered, Converter={StaticResource OrderStatusToImageConverter}, Mode=OneWay}"/>
<TextBlock Margin="25,5,25,5" Text="{Binding Customer.CustomerName, FallbackValue=N/A, Mode=OneWay}" FontSize="20"/>
</StackPanel>
最后是视觉效果。
我需要使用 C# MVVM 解决以下问题。我正在使用以下模型。
我的一个 UserControl 得到了以下 ListBox 模板。
<ListBox ItemsSource="{Binding OrdersListViewViewModel.AllItems, Source={StaticResource Locator}}" SelectedItem="{Binding OrdersListViewViewModel.SelectedItem, Source={StaticResource Locator}}" Background="White">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" Margin="0 0 0 0" Height="Auto" Width="Auto" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,7,0,6" HorizontalAlignment="Left" Orientation="Horizontal">
<Image Width="25" Height="25" Margin="5 2 0 0" Source="{Binding OrdersListViewViewModel.OrderDeliveryStateImage, Mode=OneWay, Source={StaticResource Locator}}"/>
<TextBlock Margin="25,5,25,5" Text="{Binding OrdersListViewViewModel.AllItems/Customer.CustomerName, FallbackValue=N/A, Mode=OneWay, Source={StaticResource Locator}}" FontSize="20"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
该列表显示了从数据库加载的所有订单(客户名称)。我想用图片填充在 TextBlock 旁边的图像。如果订单下的所有orderitems都已发货(Delivered=1)应该用picture1,否则用picture2.
所以我要绑定 ObservableCollection<Order>
。模型是使用 entity framework(数据库优先)从 .tt 生成的,因此由于可能的数据库更新,将计算直接放入 Order.cs class 是个坏主意。
我的第一个想法是使用 MSSQL Computed 列,但我认为这不是一个好的方法(解决方案中可能有很多这样的情况)所以模型会庞大而复杂。
第二个想法是使用转换器,但它应该用于简单的任务,而不是用于计算逻辑(这是)。
第三个想法是将 ObservableCollection<Order>
更改为 ObservableCollection<Tuple<string,Order>>
并以某种方式将其绑定到视图但是......你知道,这是个坏主意。
所以我的问题很简单。我如何使用 MVVM 最佳实践解决这个问题(在哪里放置计算逻辑)。
谢谢。
经过谷歌搜索,我决定创建此解决方案。也许它会对某人有所帮助。 首先,我创建了部分 class 订单实体以分隔文件,因此当 entity framework 更新订单实体时,它不会覆盖我的自定义。
然后我创建了自定义 属性 来确定订单是否已交付。所以计算逻辑还是停留在模型上。
public partial class Order
{
public bool IsOrderDelivered
{
get
{
int orderDelivered = 1;
foreach (var orderItem in this.OrderItems)
{
orderDelivered = orderDelivered * orderItem.Delivered;
}
return orderDelivered == 1 ? true : false;
}
}
}
然后我创建了转换器,它只是将布尔值转换为文本,这就是它存在的原因,并且使用正确。
public class OrderStatusToImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (bool)value == true ? @"Skins\approved.png" : @"Skins\denied.png";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
并在部分 class 中与转换器一起在我的新 属性 上创建了数据绑定。
<StackPanel Margin="0,7,0,6" HorizontalAlignment="Left" Orientation="Horizontal">
<Image Width="25" Height="25" Margin="5 2 0 0" Source="{Binding IsOrderDelivered, Converter={StaticResource OrderStatusToImageConverter}, Mode=OneWay}"/>
<TextBlock Margin="25,5,25,5" Text="{Binding Customer.CustomerName, FallbackValue=N/A, Mode=OneWay}" FontSize="20"/>
</StackPanel>
最后是视觉效果。