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基礎元素屬性等等;
ViewModel是視圖模型層,是MVVM實現業務邏輯代碼的地方;
例如:操作視圖界面數據的呈現,界面按鈕觸發的事件和操作數據庫前后對界面交互的事件;
View是視圖層,是窗體布局實現的地方;也就是呈現給用戶交互使用的界面窗體;
例如:登錄頁面,查詢頁面,新增和編輯的頁面等;
Resources是資源庫層,里面存放聲音,圖片和樣式布局等統一調用外部資源的地方;
Lib是引用層,放置一些第三方引用便于調用,也可以用nuget統一管理第三方dll;
Service是服務層,是實現對數據庫或者對站點接口的操作,進行數據持久化和數據交互;
Common是工具層,是存放一些公共的代碼,統一調用,簡潔業務邏輯代碼的冗余;
注:可以建文件夾,但更推薦新建類庫放置以上層級;
3. 控件的使用與布局;
3.1 從工具箱中直接拖拉控件;
3.2 直接在代碼中編輯控件代碼;
4. 代碼關聯;
4.1 View與ViewModel的交互關聯:
- View后臺的代碼關聯
public MainWindow() //類名 {InitializeComponent();
//后臺代碼有這句就實現了View和ViewModel的綁定DataContext = new MainWindowViewModel();
}
?
- 文本的綁定?
前端:<TextBox Text="{Binding TxtInput}"/>
后端:
public string TxtInput
{
get => _txtInput;
set
{
_txtInput = value;
//用RaisePropertyChanged刷新前端綁定控件的輸入框文本內容
RaisePropertyChanged("TxtInput");?
}
}
private string _txtInput;
?
- 事件的綁定
前端:<Button Content="添加" Command="{Binding BtnAddContent}"/>
后端:
public MainWindowViewModel()?
{
//按鈕事件與業務的銜接? ?也可以在BtnAddContent的Set中寫
BtnAddContent = new RelayCommand(AddContent);
}
//前端綁定的 添加按鈕 Command事件
public RelayCommand BtnAddContent { get; set; }
private void AddContent()
{
? //按鈕事件處理的業務邏輯代碼
}
?
- 樣式的綁定
<TextBox Style="{StaticResource TxbTrigger}" Tag="序號..." /><Button Content="添加" Template="{StaticResource DefaultButton}" />
”TxbTrigger是輸入框水印樣式資源,DefaultButton是按鈕樣式資源模板;詳細樣式代碼,查閱源碼中的Resources-Style;“
4.2 數據綁定和命令綁定的代碼(如果用第三方框架引用,就不需要編寫以下兩個方法類)
//數據綁定
public class ViewModelBase : INotifyPropertyChanged{public event PropertyChangedEventHandler PropertyChanged;protected void RaisePropertyChanged<T>(Expression<Func<T>> action){var propertyName = GetPropertyName(action);RaisePropertyChanged(propertyName);}private static string GetPropertyName<T>(Expression<Func<T>> 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 ObservableCollection<AddModel> AddContent{get => _addContent;set{_addContent = value;RaisePropertyChanged("AddContent"); }}private ObservableCollection<AddModel> _addContent =
new ObservableCollection<AddModel>();
"AddModel"是Model中的屬性類;代表DataGrid中綁定的列名指向;
DataGrid前端代碼:
<DataGrid x:Name="DgTimes"
ItemsSource="{Binding AddContent}" AutoGenerateColumns="False"SelectedItem="{Binding SelectTime,UpdateSourceTrigger=PropertyChanged}"><DataGrid.InputBindings>
<!--雙擊事件--><MouseBinding Gesture="LeftDoubleClick" Command="{Binding DgDoubleClick}" CommandParameter="{Binding ElementName=DgTimes,Path=SelectedItem}"/><!--單擊事件,也可以在SelectedItem選中事件中的set屬性編輯業務代碼-->
<MouseBinding Gesture="LeftClick" Command="{Binding DgClick}"CommandParameter="{Binding ElementName=DgTimes,Path=SelectedItem}"/></DataGrid.InputBindings><DataGrid.Columns><DataGridTextColumn Header="序號" Binding="{Binding RowIndex}"/><DataGridTemplateColumn Header="勾選?" MinWidth="30"><DataGridTemplateColumn.CellTemplate><DataTemplate><Grid>
<!--圖片的綁定,注意不能為null或者空值,不然會加載超慢--><Image Width="20" Height="20" Source="{Binding Photo}"/></Grid></DataTemplate></DataGridTemplateColumn.CellTemplate></DataGridTemplateColumn><DataGridTextColumn Header="輸入內容" Binding="{Binding AddContent}"/><DataGridTextColumn Header="時間" Binding="{Binding AddTime}"/></DataGrid.Columns> </DataGrid>
?注:由于整個制作項目的操作視頻文件過大,如有所需,留郵箱地址給博主;
5. 執行效果;
?
五、注意事項
本次項目制作并沒有使用數據庫的操作;源代碼中也是沒有!
源碼中包括了對輸入框限制數字的輸入方法;
源碼中包括了Button,TextBox,CheckBox,DataGrid等等樣式資源代碼;
有些網友推薦 MVVMLight 或者 Prism 等第三方MVVM框架引用;
?
?六、下篇預告
在制作WPF過程中遇到的問題以及解決方案;
其中包括:焦點的控制,鍵盤事件觸發,輸入框的數字限制,異步處理,隱藏狀態可用狀態,自定義屬性等等...
?
?