WPF项目搭建
版权声明:本文为博主初学经验,未经博主允许不得转载。
一、前言
记录在学习与制作WPF过程中遇到的解决方案。
使用MVVM的优点是 数据和视图分离,双向绑定,低耦合,可重用行,相对独立的设计和逻辑;
二、配置
系统环境:
win10
开发工具:
Visual Studio 2017
开发语言:
C#.WPF (MVVM框架)
数据库:
SQLiteStudio
三、附件
- vs_enterprise.exe 在线安装 Visual Studio 2017 开发工具;
- SQLiteStudio.zip 免安装Sqlite轻量数据库操作工具;
- WPF-MVVM-Work.zip 项目源代码;
四、步骤
1. 创建项目;
2. 文件夹层级;
建文件夹:Model,ViewModel,View,Resources,Lib,Service,Common;
Model是模型层,属性类存放的地方;也就是存放不涉及业务逻辑的代码;
例如:列表元素,接口参数,枚举,数据交互的参数模型和View基础元素属性等等;
ViewMode是视图模型层,是MVVM实现业务逻辑代码的地方;
例如:操作视图界面数据的呈现,界面按钮触发的事件和操作数据库前后对界面交互的事件;
View是视图层,是窗体布局实现的地方;也就是呈现给用户交互使用的界面窗体;
例如:登录页面,查询页面,新增和编辑的页面等;
Resources是资源库层,里面存放声音,图片和样式布局等统一调用外部资源的地方;
Lib是引用层,放置一些第三方引用便于调用,也可以用nuget统一管理第三方dll;
Service是服务层,是实现对数据库或者对站点接口的操作,进行数据持久化和数据交互;
Common是工具层,是存放一些公共的代码,统一调用,简洁业务逻辑代码的冗余;
注:可以建文件夹,但更推荐新建类库放置以上层级;
3. 控件的使用与布局;
3.1 从工具箱中直接拖拉控件;
3.2 直接在代码中编辑控件代码;
4. 代码关联;
4.1 View与ViewModel的交互关联:
- View后台的代码关联
public MainWindow() //类名 { InitializeComponent(); DataContext = new MainWindowViewModel();//后台代码有这句就实现了View和ViewModel的绑定
}
- 文本的绑定
前端:"{Binding TxtInput}"/>
后端:
public string TxtInput
{
get => _txtInput;
set
{
_txtInput = value;
RaisePropertyChanged("TxtInput"); //用于刷新绑定的输入框
}
}
private string _txtInput;
- 事件的绑定
前端:
public MainWindowViewModel()
{
BtnAddCOntent= new RelayCommand(AddContent);
}
public RelayCommand BtnAddContent { get; set; }
private void AddContent()
{
//按钮事件处理的业务逻辑代码
}
- 样式的绑定
"{StaticResource TxbTrigger}" Tag="序号..." />
”TxbTrigger是输入框水印样式资源,DefaultButton是按钮样式资源模板;详细样式代码,查阅源码中的Resources-Style;“
4.2 数据绑定和命令绑定的代码
public class ViewModelBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void RaisePropertyChanged(Expression > action) { var propertyName = GetPropertyName(action); RaisePropertyChanged(propertyName); } private static string GetPropertyName (Expression > action) { var expression = (MemberExpression)action.Body; var propertyName = expression.Member.Name; return propertyName; } public void RaisePropertyChanged(string propertyName) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } }
public class RelayCommand : ICommand { public Action ExecuteAction; //执行方法 public Action<object> ExecuteCommand; //执行方法 带参数 public Func<object, bool> CanExecuteCommand; //执行方法的条件 public RelayCommand(Action action)// 执行事件 { ExecuteAction = action; } public RelayCommand(Action<object> action)// 执行带参数的事件 { ExecuteCommand = action; } public RelayCommand(Action<object> action, Func<object, bool> can)// 根据条件执行带参数的事件 { ExecuteCommand = action; CanExecuteCommand = can; } public event EventHandler CanExecuteChanged;// 当命令可执行状态发生改变时,应当被激发 public bool CanExecute(object parameter)// 用于判断命令是否可以执行 { if (ExecuteAction != null) return true; return CanExecuteCommand == null || CanExecuteCommand(parameter); } public void Execute(object parameter)//命令执行 { if (ExecuteCommand != null) ExecuteCommand(parameter); else ExecuteAction(); } }
ViewModel的业务类需要继承ViewModelBase
public class MainWindowViewModel : ViewModelBase
前端的DataGrid绑定的数据需要用ObservableCollection类型定义列表;
public ObservableCollectionAddContent { get => _addContent; set { _addContent = value; RaisePropertyChanged("AddContent"); } } private ObservableCollection _addCOntent= new ObservableCollection ();
"AddModel"是Model中的属性类;代表DataGrid中绑定的列名指向;
DataGrid前端代码:
"False" x:Name="DgTimes" ItemsSource="{Binding AddContent}" SelectedItem="{Binding SelectTime,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"> "LeftDoubleClick" Command="{Binding DgDoubleClick}" CommandParameter="{Binding ElementName=DgTimes, Path=SelectedItem}" /> "LeftClick" Command="{Binding DgClick}" CommandParameter="{Binding ElementName=DgTimes, Path=SelectedItem}"/> "序号" Binding="{Binding RowIndex}"/> "勾选?" Min30"> 20" 20" Source="{Binding Photo}"/> "输入内容" Binding="{Binding AddContent}"/> "时间" Binding="{Binding AddTime}"/>
5. 执行效果;
五、注意事项
本次项目制作并没有使用数据库的操作;源代码中也是没有!
源码中包括了对输入框限制数字的输入方法;
源码中包括了Button,TextBox,CheckBox,DataGrid等等样式资源代码;
有些网友推荐 MVVMLight 或者 Prism 等第三方MVVM框架引用;
WPF做动画效果会很耗电脑资源,并且不会有性能优化;
WPF使用异步的时候注意回到前端主线程才可以调用前端属性;
MVVM只是推荐使用,要结合业务需求灵活变动使用,不是硬性规范;
使用第三方控件和自定义属性会导致开发时界面灰掉;(暂时没找到解决方案)
DataGrid加载不明确的图片,会加载超级慢;DataGrid默认开启数据虚化,会导致滚动条加载慢;