通常情况下,你希望你的模型只是一个简单的数据传输对象。当你执行数据库查询时,你会得到一个简单的模型返回,它不会进行任何转换,因为否则你就没有遵循SOLID原则中的关注点分离。然而,稍微作弊一下不会杀死你,但这可能会使调试某些事情变得有点沮丧,因为大多数人不会预期他们的POCO(普通旧CLR对象)启动任何业务逻辑。
以下是一些代码:
一些设置类:
ViewModelBase.cs
ViewModelBase是galasoft中一个“更聪明”的版本,这个坏小子自动连接设计时间视图模型(你会喜欢这个)。
namespace WPFPlayground.ViewModel
{
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void SetValue<T>(ref T property, T value, [CallerMemberName] string propertyName = null)
{
if (property != null)
{
if (property.Equals(value)) return;
}
OnPropertyChanged(propertyName);
property = value;
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
DefectiveToBackgroundColorConverter.cs
一个值转换器,在视图上显示我们的产品时使用(稍后您将看到它被引用):
using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Media;
namespace WPFPlayground
{
public class DefectiveToBackgroundColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (System.Convert.ToBoolean(value))
{
return new SolidColorBrush(Colors.Red);
}
return new SolidColorBrush(Colors.White);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return Binding.DoNothing;
}
}
}
使用模型优先方法:
ProductModel.cs
POCO数据传输对象
namespace WPFPlayground.Model
{
public class ProductModel
{
public string Name { get; set; }
public bool IsDefective { get; set; }
}
}
ProductViewModel.cs
注意使用setvalue自动连接notifypropertychanged事件。
namespace WPFPlayground.ViewModel
{
public class ProductViewModel : ViewModelBase
{
private string _name;
private bool _isDefective;
public bool IsDefective
{
get { return _isDefective; }
set { SetValue(ref _isDefective, value); }
}
public string Name
{
get { return _name; }
set { SetValue(ref _name, value); }
}
}
}
我们有一个ProductModel和一个ProductViewModel。一个在你与数据库交互时处理所有工作,一个在你绑定视图时处理所有工作。
所以我们需要一个仅代表单个ProductViewModel的视图:
ProductView.xaml
注意使用背景颜色转换器来处理触发器。
<UserControl x:Class="WPFPlayground.View.ProductView"
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:wpfPlayground="clr-namespace:WPFPlayground"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance wpfPlayground:DesignProductViewModel, IsDesignTimeCreatable=True}">
<UserControl.Resources>
<wpfPlayground:DefectiveToBackgroundColorConverter x:Key="DefectiveToBackgroundColorConverter" />
</UserControl.Resources>
<Viewbox>
<Border Width="500" Background="{Binding IsDefective, Converter={StaticResource DefectiveToBackgroundColorConverter}}">
<TextBlock Text="{Binding Name}" FontSize="40" TextWrapping="Wrap" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Border>
</Viewbox>
</UserControl>
接下来我们需要设计时的视图模型,以便在设计时查看我们的 XAML:
DesignProductViewModel.cs
虽然有点无聊,但可以使设计时工作正常运行!
using WPFPlayground.ViewModel;
namespace WPFPlayground
{
public class DesignProductViewModel : ProductViewModel
{
public DesignProductViewModel()
{
Name = "This is my product";
IsDefective = true;
}
}
}
现在我们需要显示这些视图模型的列表:
MainWindow.xaml
使用ItemsControl,每天都可以轻松完成。
<Window x:Class="WPFPlayground.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModel="clr-namespace:WPFPlayground.ViewModel"
xmlns:view="clr-namespace:WPFPlayground.View"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" d:DataContext="{d:DesignInstance viewModel:DesignProductsViewModel, IsDesignTimeCreatable=True}">
<Window.Resources>
<DataTemplate DataType="{x:Type viewModel:ProductViewModel}">
<view:ProductView />
</DataTemplate>
</Window.Resources>
<StackPanel>
<ItemsControl ItemsSource="{Binding Products}">
<view:ProductView />
</ItemsControl>
</StackPanel>
</Window>
DesignProductsViewModel.cs
这是设计时视图模型,您可以在设计时查看其工作原理。它会生成一组随机的产品,以便更轻松地进行设计。
using System;
using System.Collections.ObjectModel;
using System.Linq;
namespace WPFPlayground.ViewModel
{
public class DesignProductsViewModel : ProductsViewModel
{
public DesignProductsViewModel()
{
var random = new Random();
Products = new ObservableCollection<ProductViewModel>(Enumerable.Range(1, 5).Select(i => new ProductViewModel
{
Name = String.Format(@"Product {0}", i),
IsDefective = (random.Next(1, 100) < 50)
}));
}
}
}