zhixiangshu-jie

WPF基于.Net Core

因为最近.net core的热门,所以想实现一下.net core框架下的WPF项目,还是MVVM模式,下面就开始吧,简单做一个计算器吧。

  • 使用VS2019作为开发工具

  • 实现MVVM模式

1、实现基础项目

使用VS2019新建WPF App项目

![image-20200710193416617](C:\Users\fangzhongwei\Desktop\WPF Net Core\image\image-20200710193416617.png)

项目名称Common

1.1、修改项目属性

  • 删除项目MainWindow.xaml以及MainWindow.xaml.cs文件

  • 删除App.xaml和App.xaml.cs文件

  • 修改项目输出为类库

    ![image-20200710193806136](C:\Users\fangzhongwei\Desktop\WPF Net Core\image\image-20200710193806136.png)

  • 添加Command文件夹

    ![image-20200710193823822](C:\Users\fangzhongwei\Desktop\WPF Net Core\image\image-20200710193823822.png)

2.2、实现ICommand接口

定义BaseCommand类实现ICommand接口

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Input;

namespace Common.Command
{
    /// <summary>
    /// 实现ICommand接口
    /// </summary>
    public class BaseCommand : ICommand
    {
        public Predicate<object> CanExecuteDelegate { get; set; }
        public Action<object> ExecuteDelegate { get; set; }

        public BaseCommand(Action<object> execute)
        {
            ExecuteDelegate = execute;
        }

        public BaseCommand(Action<object> execute, Predicate<object> canExecute)
        {
            CanExecuteDelegate = canExecute;
            ExecuteDelegate = execute;
        }

        public BaseCommand()
        {
        }

        /// <summary>
        /// Defines the method that determines whether the command can execute in its current state.
        /// </summary>
        public bool CanExecute(object parameter)
        {
            if (CanExecuteDelegate != null)
                return CanExecuteDelegate(parameter);
            return true;
        }

        /// <summary>
        /// Occurs when changes occur that affect whether the command should execute.
        /// </summary>
        public event EventHandler CanExecuteChanged
        {
            add
            {
                CommandManager.RequerySuggested += value;
            }

            remove
            {
                CommandManager.RequerySuggested -= value;
            }
        }

        /// <summary>
        /// 执行
        /// </summary>
        public void Execute(object parameter)
        {
            try
            {
                if (ExecuteDelegate != null)
                    ExecuteDelegate(parameter);
            }
            catch (Exception ex)
            {
                string moudle = ExecuteDelegate.Method.DeclaringType.Name + ":" + ExecuteDelegate.Method.Name;
            }
        }

        /// <summary>
        /// Raises the CanExecuteChanged event.
        /// </summary>
        public void InvalidateCanExecute()
        {
            CommandManager.InvalidateRequerySuggested();
        }
    }
}

2.3、实现INotifyPropertyChanged接口

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;

namespace Common.Command
{
    /// <summary>
    /// 实现INotifyPropertyChanged接口
    /// </summary>
    public class NotifyPropertyBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;


        public void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public object Clone()
        {
            return this.MemberwiseClone();
        }
    }
}

2、主程序HelloCore

2.1、新建WPF APP项目

项目名称为HelloCore

新建View、ViewModel、Model三个文件夹

![image-20200711130227939](C:\Users\fangzhongwei\Desktop\WPF Net Core\image\image-20200711130227939.png)

删除MainWindow.xaml

![image-20200711130756699](C:\Users\fangzhongwei\Desktop\WPF Net Core\image\image-20200711130756699.png)

2.2、添加窗体MainView.xaml

![image-20200711131905603](C:\Users\fangzhongwei\Desktop\WPF Net Core\image\image-20200711131905603.png)

修改MainView.xaml

<Window x:Class="HelloCore.View.MainView"
        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:local="clr-namespace:HelloCore.View"
        mc:Ignorable="d"
        Title="HelloCore" Height="350" Width="600">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <TextBox Text="{Binding Result}" Margin="5"/>
        <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
            <Button Content="HelloCore" Command="{Binding HelloCommand}" Margin="10" Width="80" Height="30"/>
            <Button Content="Clear" Command="{Binding ClearCommand}" Margin="10" Width="80" Height="30"/>
        </StackPanel>
    </Grid>
</Window>

2.3、添加MainViewModel.cs文件

![image-20200711133707892](C:\Users\fangzhongwei\Desktop\WPF Net Core\image\image-20200711133707892.png)

using Common.Command;
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Input;

namespace HelloCore.ViewModel
{
    public class MainViewModel : NotifyPropertyBase
    {
        private string _result;

        /// <summary>
        /// 绑定到界面上TextBox的Text属性上
        /// </summary>
        public string Result
        {
            get
            {
                return _result;
            }
            set
            {
                _result = value;
                OnPropertyChanged("Result");
            }
        }

        private ICommand _helloCommand;
        private ICommand _clearCommand;

        public ICommand HelloCommand
        {
            get
            {
                return this._helloCommand ?? (this._helloCommand = new BaseCommand()
                {
                    CanExecuteDelegate = x => true,
                    ExecuteDelegate = x =>
                    {
                        Result = "Hello Net Core";
                    }
                });
            }
        }

        public ICommand ClearCommand
        {
            get
            {
                return this._clearCommand ?? (this._clearCommand = new BaseCommand()
                {
                    CanExecuteDelegate = x => true,
                    ExecuteDelegate = x =>
                    {
                        Result = "";
                    }
                });
            }
        }
    }
}

2.4、通过DataContext绑定

在MainView.xaml.cs中添加DataContext进行MainView和MainViewModel的绑定

using HelloCore.ViewModel;
using System.Windows;

namespace HelloCore.View
{
    /// <summary>
    /// MainView.xaml 的交互逻辑
    /// </summary>
    public partial class MainView : Window
    {
        MainViewModel vm = new MainViewModel();
        public MainView()
        {
            InitializeComponent();
            this.DataContext = vm;
        }
    }
}

2.5、修改App.xmal文件

修改App.xaml文件,删除StartupUri,添加启动事件以及异常捕捉事件

![image-20200711131032509](C:\Users\fangzhongwei\Desktop\WPF Net Core\image\image-20200711131032509.png)

<Application x:Class="HelloCore.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:HelloCore"
             Startup="Application_Startup"
             DispatcherUnhandledException="Application_DispatcherUnhandledException">
    <Application.Resources>
         
    </Application.Resources>
</Application>

2.6、修改App.xaml.cs文件

using HelloCore.View;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;

namespace HelloCore
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        MainView mainWindow;
        public App()
        {
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledExceptionEventHandler);
        }

        private static void UnhandledExceptionEventHandler(object sender, UnhandledExceptionEventArgs e)
        {

        }

        /// <summary>
        /// 重写Starup函数,程序重这里启动
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Application_Startup(object sender, StartupEventArgs e)
        {
            mainWindow = new MainView();
            mainWindow.Show();
        }

        /// <summary>
        /// 异常处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            // .Net4.0及之前版本访问剪切板默写情况下可能失败报异常
            // OpenClipboard HRESULT:0x800401D0 (CLIPBRD_E_CANT_OPEN))
            var comException = e.Exception as System.Runtime.InteropServices.COMException;
            if (comException != null && comException.ErrorCode == -2147221040)
            {
                e.Handled = true;
            }

            // 未捕获的异常
            e.Handled = true;
        }
    }
}

2.7、启动程序,观看结果

到这里一个简单的基于.net core的WPF应用程序就完成啦,当然WPF真正的魅力没有展示出来,MVVM模式的意义大概是这样了,实现View和Model的分离

![image-20200711134557199](C:\Users\fangzhongwei\Desktop\WPF Net Core\image\image-20200711134557199.png)

相关文章: