wpf Prism 实现MVVM
用C#写程序也有好几个年头了,一直都停留在很基础的阶段。今年抽空学了一下用EF6去访问数据库,后来考虑到手持段的共同开发,考虑数据用Django Restful去实现,C# wpf和Android 一起作为客户端去访问。
于是遇到一个共同的问题:如何用MVVM简化开发。以前看到这种术语我个人比较排斥,因为我编程序是从汇编开始的,喜欢从新造*,而且*也造得不好。
Prism是C#上面一个MVVM的工具,于是我今天上午捣鼓了一下,参照Prism官网的方法,搭建了一下脚手架。
MVVM帮我们把“干活”的代码,和“显示”的代码分开了,确实很清楚。按照Prism的要求,文件夹也是老老实实得建,尤其是Views和ViewModels,一定要逐个字母检查。因为它有一个默认的“从View寻找ViewModel”的机制,会去关联这两个文件夹。
因为我创建项目时,没有先去建这两个文件夹,把文件分类,导致View和Viewmodel没有能够关联上。查阅了很多英文资料才发现这个问题,于是改了文件夹(还不够,还得看看文件里的namespace是否也改过来了)
只是系统里面一个录入界面,我们仓储部的同事有时候需要去机器上做一下入库(大部分入库是检验部同事做的)。
最近我尝试了wpf之后,我发现确实比winform好用,而且漂亮,特别是引用了谷歌的MaterialDesign之后,界面美观很多。
从普通的wpf项目,改成使用Prism框架,需要改几个地方(请注意所有出现prism的地方
步骤一 按照MVVM的标准,创建文件夹(也可以叫做Module吧?好像android studio这么叫)
步骤二 修改App.xaml
<prism:PrismApplication x:Class="WpfDog.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfDog"
xmlns:prism="http://prismlibrary.com/"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<materialDesign:BundledTheme BaseTheme="Light" PrimaryColor="DeepPurple" SecondaryColor="Lime" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</prism:PrismApplication>
步骤三 修改App.xaml.cs
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using Prism.Ioc;
using Prism.Unity;
namespace WpfDog
{
/// <summary>
/// App.xaml 的交互逻辑
/// </summary>
public partial class App : PrismApplication
{
protected override Window CreateShell()
{
Views.CheckInRoll w = Container.Resolve<Views.CheckInRoll>();
return w;
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.Register<Services.IRoll, Services.DbRollStock>();
// throw new NotImplementedException();
}
}
}
步骤四 创建 Viewmodel
当然我代码里很多都是初始化不需要看,大家看看大概的结构就可以了。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Prism.Commands;
using Prism.Mvvm;
using System.Diagnostics;
using WpfDog.Models;
namespace WpfDog.ViewModels
{
class CheckInRollViewModel:BindableBase
{
public CheckInRollViewModel(Services.DbRollStock rollStock)
{
_rollStock = rollStock;
//test
_rolllist.Add(new Roll { id=1,productName="2028",productType="1",length= 40.5F});
_rolllist.Add(new Roll { id = 1, productName = "2028", productType = "1", length = 40.5F });
_rolllist.Add(new Roll { id = 1, productName = "2028", productType = "1", length = 40.5F });
}
//服务器访问相关
private Services.DbRollStock _rollStock = null;
//新入库布卷清单
private ObservableCollection<Roll> _rolllist = new ObservableCollection<Roll>();
public ObservableCollection<Roll> RollList {
get { return _rolllist; }
set { _rolllist = value; }
}
//输入字符串
private string _inputStr = "Hello World";
public String InputStr
{
get => _inputStr;
set {
SetProperty(ref _inputStr, value); }
}
//命令操作
private DelegateCommand _commandLoad = null;
public DelegateCommand CommandLoad =>
_commandLoad ?? (_commandLoad = new DelegateCommand(CommandLoadExecute));
private void CommandLoadExecute()
{
RollList.Clear();
List<Roll> list = _rollStock.GetAll();
foreach(Roll item in list)
{
RollList.Add(item);
}
}
}
}
步骤五 创建View
注意 view和步骤四中创建的viewmodel,名字一定要一样,比如SampleView搭配SampleViewViewModel,Prism才会帮你去自动关联上。当然这种关联方式我们也可以手动配置,目前我还不需要去了解这个,我想先用起来再说。
我利用业余时间写这些代码,一来是个人爱好,二来也是想提高我们工厂的工作效率,三来也可以节省一些开发费用。(当然我们也可以完全找软件公司去做这个事情)
目前开发上面,我涉及到的知识点有:
服务器
Ubuntu,Mysql,Php,Nigix,Django
UI
android,c#wpf,c#winform,javascript,jquery,bootstrap
对于学习新的语言和技术,我觉得不想再多学了。但是对于设计模式和思想,我觉得还可以再深入一些。有时候从这些思想里面,还能悟出其他道理呢!
一些我犯的错误:
类里面的get set
面向对象编程没什么基础,以为创建类就是定义几个成员变量和函数就可以,哪知道还有get set这个东西——因为没有用get set去"再定义”成员变量,导致在绑定datagrid的时候,vs 2017提示我找不到property.
<DataGrid Width="250"
ItemsSource="{Binding RollList}"
>
<DataGrid.Columns>
<DataGridTextColumn Width=" auto" Header="序号" Binding="{Binding id}"/>
<DataGridTextColumn Width=" auto" Header="型号" Binding="{Binding productName}"/>
<DataGridTextColumn Width=" auto" Header="颜色" Binding="{Binding productType}"/>
<DataGridTextColumn Width=" auto" Header="长度" Binding="{Binding length}"/>
</DataGrid.Columns>
于是我在模型类中添加了get set
public class Roll
{
public int id { get; set; }
public String productName { get; set; }
public String productType { get; set; }
public float length { get; set; }
}
于是我们可以看到datagrid和Rolllist绑定起来了。