一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

WPF框架教程 | 從0到1:使用Caliburn.Micro(WPF和MVVM)開發(fā)簡單的計算器

 大白技術(shù)控 2020-02-02


之前時間一直在使用Caliburn.Micro這種應(yīng)用了MVVM模式的WPF框架做開發(fā),是時候總結(jié)一下了。

Caliburn.Micro(https://blog.csdn.net/lzuacm/article/details/78886436)是一個輕量級的WPF框架,簡化了WPF中的不少用法,推薦做WPF開發(fā)時優(yōu)先使用。

真正快速而熟練地掌握一門技術(shù)就可以嘗試著用最快的速度去構(gòu)建一個玩具項目(Toy project),然后不斷地優(yōu)化、重構(gòu)之。比如本文將介紹如何使用Caliburn.Micro v3.2開發(fā)出一個簡單的計算器,里面用到了C#中的async異步技術(shù),Caliburn.Micro中的Conductor等等~

>>>1.在VS中創(chuàng)建WPF項目<<<

>>>2.使用NuGet包管理工具為當前項目安裝Caliburn.Micro <<<

對于Caliburn.Micro 1.x和2.x版,只能使用.dll,需手動給項目加Reference。而3.0以后的版本可使用NuGet包管理工具來管理,安裝和卸載既方便又徹底,推薦使用。(ps: NuGet之于Visual Studio(C++, C#等), 猶pip之于Python, npm之于node, maven之于Java, gem之于Ruby等等)

>>>3.框架搭建  <  <  <

  1. 刪除項目根目錄下的MainWindow.xaml

  2. 按下圖調(diào)整 App.xaml
    刪除語句

    StartupUri="MainWindow.xmal"。

  3. 填充Application.Resources

<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<local:Bootstrapper x:Key="bootstrapper"/>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>

   4 . 創(chuàng)建Bootstrapper類
然后讓其繼承自BootstrapperBase類,并加上構(gòu)造函數(shù),另外再重寫函數(shù)OnStartup即可。


using System.Windows;
using Caliburn.Micro;
using CaliburnMicro_Calculator.ViewModels;

namespace CaliburnMicro_Calculator
{
public class Bootstrapper : BootstrapperBase
{
public Bootstrapper()
{
Initialize();
}

protected override void OnStartup(object obj, StartupEventArgs e)
{
DisplayRootViewFor<ShellViewModel>();
}
}
}

   5 . 在項目目錄下新建Models, ViewModels, Views這3個文件夾
在ViewModel文件夾中添加ShellViewModel.cs,并創(chuàng)建Left, Right和Result這3個屬性。

需要注意的是 ShellViewModel.cs需要繼承類 

Screen 和 INotifyPropertyChanged(用于感知并同步所綁定屬性的變化),ShellViewModel具體代碼為:


using System.ComponentModel;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using Caliburn.Micro;

namespace CaliburnMicro_Calculator.ViewModels
{
public class ShellViewModel : Screen, INotifyPropertyChanged
{
private double _left;
private double _right;
private double _result;

public double Left
{
get { return _left; }
set
{
_left = value;
NotifyOfPropertyChange();
}
}

public double Right
{
get { return _right; }
set
{
_right = value;
NotifyOfPropertyChange();
}
}

public double Result
{
get { return _result; }
set
{
_result = value;
NotifyOfPropertyChange();
}
}
}

說明: 最開始布局xaml時,設(shè)計位置時采用的是左(operand 1), 中(operand 2), 右(result),于是屬性值使用了Left, Right和Result。

>>>4.設(shè)計XAML并綁定屬性 <   <  <

在Views文件夾中創(chuàng)建Window,命名為ShellView.xaml,在Views文件夾下創(chuàng)建子文件夾Images,用于存放+,-,*,/這4種操作對應(yīng)的小圖標,其具體代碼如下:

<Window x:Class="CaliburnMicro_Calculator.Views.ShellView"
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./markup-compatibility/2006"
xmlns:local="clr-namespace:CaliburnMicro_Calculator.Views"
xmlns:cal="http://www."
mc:Ignorable="d"
Title="Calculator" SizeToContent="Height" Width="240">


<StackPanel Background="Beige">
<StackPanel Orientation="Horizontal">
<Label Margin="10"
Target="{Binding ElementName=left}">

Operand _1:
</Label>
<TextBox Margin="10"
Width="72"
x:Name="left"/>

</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Margin="10"
Target="{Binding ElementName=right}">

Operand _2:
</Label>
<TextBox Margin="10"
Width="72"
x:Name="right"/>

</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Margin="10"
x:Name="btnPlus"
cal:Message.Attach="[Event Click]=[Action Plus(left.Text, right.Text):result.Text]">

<Image Source="Images/op1.ICO"/>
</Button>

<Button Margin="10"
x:Name="btnMinus"
cal:Message.Attach="[Event Click]=[Action Minus(left.Text, right.Text):result.Text]">

<Image Source="Images/op2.ICO"/>
</Button>

<Button Margin="10"
x:Name="btnMultiply"
cal:Message.Attach="[Event Click]=[Action Multipy(left.Text, right.Text):result.Text]">

<Image Source="Images/op3.ICO"/>
</Button>

<Button Margin="10"
x:Name="btnDivide" IsEnabled="{Binding Path=CanDivide}"
cal:Message.Attach="[Event Click]=[Action Divide(left.Text, right.Text):result.Text]">

<Image Source="Images/op4.ICO"/>
</Button>

</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Margin="10">
Answer:
</Label>
<TextBox Margin="10"
Width="72"
Text ="{Binding Path=Result, StringFormat={}{0:F4}}" IsReadOnly="True" />

</StackPanel>
</StackPanel>
</Window>

說明:對操作數(shù)Operand _1和Operand _2,按Alt鍵+數(shù)字可以選中該處,這是WPF的一個特殊用法。由于計算結(jié)果不希望被修改,于是加上了屬性IsReadOnly="True"。

>>>5.設(shè)計并綁定事件  <  <  <

由于暫時只打算實現(xiàn)+, -, *, /四種操作,于是我們只需創(chuàng)建相應(yīng)的4個函數(shù)即可,由于除數(shù)是0這個操作不允許,于是需再加個判斷函數(shù)CanDivide。

Caliburn.Micro中綁定事件的寫法是:
cal:Message.Attach="[Event E]=[Action A]"

(E是操作,比如Click, MouseDown, KeyDown等等,A是ViewModel中具體的函數(shù)。)

向ShellViewModel中加入事件中要做的事,此時ShellViewModel為:

using System.ComponentModel;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using Caliburn.Micro;

namespace CaliburnMicro_Calculator.ViewModels
{
public class ShellViewModel : Screen, INotifyPropertyChanged
{
private double _left;
private double _right;
private double _result;

public double Left
{
get { return _left; }
set
{
_left = value;
NotifyOfPropertyChange();
}
}

public double Right
{
get { return _right; }
set
{
_right = value;
NotifyOfPropertyChange();
}
}

public double Result
{
get { return _result; }
set
{
_result = value;
NotifyOfPropertyChange();
}
}
public bool CanDivide(double left, double right)
{
return right != 0;
}

public async void Divide(double left, double right)
{
Thread.Sleep(600);
if (CanDivide(left, right) == true)
Result = left / right;
else MessageBox.Show("Divider cannot be zero.", "Warning", MessageBoxButton.OK, MessageBoxImage.Warning);
}

public async void Plus(double left, double right)
{
Result = left + right;
}

public async void Minus(double left, double right)
{
Result = left - right;
}

public async void Multipy(double left, double right)
{
Result = left * right;
}
}
}

此時計算器的功能已基本完成,但我們可以對ViewModel進行適當?shù)恼{(diào)整:
1.創(chuàng)建新的ViewModel - CalculatorViewModel,將原來的ShellViewModel中具體的計算邏輯移入到CalculatorViewModel中;
2.此時讓ShellViewModel繼承Conductor<Object>,于是ShellViewModel擁有了管理Screen實例的功能(ViewModel中使用ActivateItem函數(shù),而View中使用X:Name="ActivateItem"標簽),其具體代碼為:

using System.ComponentModel;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using Caliburn.Micro;

namespace CaliburnMicro_Calculator.ViewModels
{
public class ShellViewModel : Conductor<object>
{
public ShellViewModel()
{
}
public void ShowCalculator()
{
ActivateItem(new CalculatorViewModel());
}
}
}

此時,CalculatorViewModel的具體代碼為:

using System.ComponentModel;
using System.Threading;
using System.Windows;
using Caliburn.Micro;

namespace CaliburnMicro_Calculator.ViewModels
{
public class CalculatorViewModel: Screen, INotifyPropertyChanged
{
private double _left;
private double _right;
private double _result;

public double Left
{
get { return _left; }
set
{
_left = value;
NotifyOfPropertyChange();
}
}

public double Right
{
get { return _right; }
set
{
_right = value;
NotifyOfPropertyChange();
}
}

public double Result
{
get { return _result; }
set
{
_result = value;
NotifyOfPropertyChange();
}
}

public CalculatorViewModel()
{
}

public bool CanDivide(double left, double right)
{
return right != 0;
}

public async void Divide(double left, double right)
{
Thread.Sleep(600);
if (CanDivide(left, right) == true)
Result = left / right;
else MessageBox.Show("Divider cannot be zero.", "Warning", MessageBoxButton.OK, MessageBoxImage.Warning);
}

public async void Plus(double left, double right)
{
Result = left + right;
}

public async void Minus(double left, double right)
{
Result = left - right;
}

public async void Multipy(double left, double right)
{
Result = left * right;
}
}
}

  3 . 對于View,只需把CalculatorViewModel對應(yīng)的CalculatorView作為ContentControl控件嵌入ShellView即可。此時ShellView的代碼調(diào)整為:

<Window x:Class="CaliburnMicro_Calculator.Views.ShellView"
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./markup-compatibility/2006"
xmlns:local="clr-namespace:CaliburnMicro_Calculator.Views"
xmlns:cal="http://www."
mc:Ignorable="d"
Title="Calculator" SizeToContent="Height" Width="240">


<Grid MinHeight="200">
<Button Content="Show Calculator" x:Name="ShowCalculator" Grid.Row="0"></Button>
<ContentControl x:Name="ActiveItem"></ContentControl>
</Grid>
</Window>

另外提一點,向ViewModel A中嵌入ViewModel B,一般來說需要做的操作是:
在A的view中使用ContentControl,綁定B的ViewModel只需使用語句cal:View.Model="{Binding BViewModel}"即可,而B的view是UserControl就可以啦。

此時CalculatorView是一個UserControl,其代碼為:

<UserControl x:Class="CaliburnMicro_Calculator.Views.CalculatorView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas./markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CaliburnMicro_Calculator.Views"
xmlns:cal="http://www."
mc:Ignorable="d"
Width="240">


<StackPanel Background="Beige">
<StackPanel Orientation="Horizontal">
<Label Margin="10"
Target="{Binding ElementName=left}">

Operand _1:
</Label>
<TextBox Margin="10"
Width="72"
x:Name="left"/>

</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Margin="10"
Target="{Binding ElementName=right}">

Operand _2:
</Label>
<TextBox Margin="10"
Width="72"
x:Name="right"/>

</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button Margin="10"
x:Name="btnPlus"
cal:Message.Attach="[Event Click]=[Action Plus(left.Text, right.Text):result.Text]">

<Image Source="Images/op1.ICO"/>
</Button>

<Button Margin="10"
x:Name="btnMinus"
cal:Message.Attach="[Event Click]=[Action Minus(left.Text, right.Text):result.Text]">

<Image Source="Images/op2.ICO"/>
</Button>

<Button Margin="10"
x:Name="btnMultiply"
cal:Message.Attach="[Event Click]=[Action Multipy(left.Text, right.Text):result.Text]">

<Image Source="Images/op3.ICO"/>
</Button>

<Button Margin="10"
x:Name="btnDivide" IsEnabled="{Binding Path=CanDivide}"
cal:Message.Attach="[Event Click]=[Action Divide(left.Text, right.Text):result.Text]">

<Image Source="Images/op4.ICO"/>
</Button>

</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Margin="10">
Answer:
</Label>
<TextBox Margin="10"
Width="72"
Text ="{Binding Path=Result, StringFormat={}{0:F4}, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="True" />

</StackPanel>
</StackPanel>
</UserControl>

好啦,就醬,由于本例中邏輯并不復(fù)雜,Model暫時用不上,對于復(fù)雜一點的項目,Model主要負責(zé)數(shù)據(jù)的讀取,如文件操作、數(shù)據(jù)庫操作、service調(diào)用等,以后有機會舉例具體來說。

如果需要持久化(persistent),則還需給給每對M-VM(Model和ViewModel)加入State,這個實際工程中也用得特別多。

>>>6.功能舉例  <  <  <

Calculator主頁:

點擊按鈕“ShowCalculator”即可看到具體的計算器~

乘法舉例:

除法舉例:

最后附上代碼:
CaliburnMicro-Calculator: A simple Calculator using Caliburn.Micro
https://github.com/yanglr/CaliburnMicro-Calculator,
歡迎fork和star,如有改進意見歡迎提交pull request~

原文地址:

https://blog.csdn.net/lzuacm/article/details/80559517


更多精彩文章,歡迎訪問本人博客https://enjoy233.cnblogs.com 或 知乎搜索Bravo Yeung.

歡迎轉(zhuǎn)發(fā)到朋友圈,公眾號轉(zhuǎn)載請后臺聯(lián)系本人申請授權(quán)~

    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    久久精品国产熟女精品| 国产一区二区三区口爆在线| 国产a天堂一区二区专区| 99精品国产自在现线观看| 成人免费观看视频免费| 夫妻性生活一级黄色录像| 国产欧美一区二区久久| 丝袜诱惑一区二区三区| 在线观看欧美视频一区| 亚洲精品福利视频你懂的| 亚洲一区二区三区三州| 午夜福利视频日本一区| 男女午夜在线免费观看视频| 亚洲欧美国产精品一区二区| 国产日韩欧美在线亚洲| 日本一本在线免费福利| 亚洲男人天堂成人在线视频| 麻豆91成人国产在线观看| 色老汉在线视频免费亚欧| 又黄又硬又爽又色的视频| 欧洲一区二区三区自拍天堂| 高清国产日韩欧美熟女| 国产精品涩涩成人一区二区三区 | 中文字幕一区二区三区大片| 熟女免费视频一区二区| 午夜久久久精品国产精品| 丰满熟女少妇一区二区三区| 精品视频一区二区三区不卡| 国产毛片不卡视频在线| 日本在线高清精品人妻| 国产老熟女超碰一区二区三区| 国产午夜在线精品视频| 国产精品免费不卡视频| 日韩人妻免费视频一专区 | 中文字幕高清免费日韩视频| 国产成人亚洲欧美二区综| 99久免费精品视频在线观| 欧美小黄片在线一级观看| 91偷拍与自偷拍精品| 伊人久久五月天综合网| 日韩在线视频精品中文字幕|