WPF 工程模版(一)

343 阅读2分钟

.gitignore

.gitignore 使用的是 github的模版.

MvvmLight

wpf 提供了数据绑定的机制,比如使用接口 INotifyPropertyChanged 或者依赖属性 DependencyProperty。但是这两个机制实现双向绑定都要写很多模版代码,开发起来令人乏味且效率低。

调研发现 mvvmlight 这个库可以比较优雅简洁的实现数据双向绑定,还提供 Command 实现事件绑定,Messenger 实现 ViewModel 间的通信,能大幅提高开发效率,必须使用。

集成

通过 NuGet 安装 MvvmLight,快速又方便。

安装后会自动修改 App.xaml, 定义一个 vm 的命名空间。

<Application.Resources>
    <ResourceDictionary>
        <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" xmlns:vm="clr-namespace:Demo.ViewModel" />
     </ResourceDictionary>
  </Application.Resources>

同时创建一个 ViewModel 文件夹,内部包含两个文件:ViewModelLocator 和 MainViewModel。

使用

ViewModelLocator

默认创建的 ViewModelLocator 文件会报错,按照提示修改即可。

// ViewModelLocator.cs
public class ViewModelLocator
{

    public ViewModelLocator()
    {
        SimpleIoc.Default.Register<MainViewModel>();
    }

    public static ViewModelLocator instance = new ViewModelLocator();

    #region ViewModel

    public MainViewModel Main => SimpleIoc.Default.GetInstance<MainViewModel>();

    #endregion
}

MainViewModel

MainViewModel 默认是 MainWindow 的 ViewModel,可以在 xaml 里进行绑定。

DataContext="{Binding Main, Source={StaticResource Locator}}"

在 ViewModel 里按照 MvvmLight 的 set 方法定义属性,即可实现双向绑定。因为 MvvmLight 在 set 方法里封装了 raisePropertyChanged 通知。

比如在 ViewModel 定义 Title 属性, xaml 文件即可绑定该属性,实现双向绑定。

// ViewModel
private string m_title;

public string Title
{
    get => m_title;
    set => Set(nameof(Title), ref m_title, value);
}
// xaml
<TextBlock Text="{Binding Title}"></TextBlock>
        

HandyControl

写页面肯定得选一个 UI 组件库,毕竟原生组件真的有些不太行。最后选定 HandyControl,下载量很高,没什么纠结的直接用。

重点提一下 HandyControl 的代码实现非常棒,我的模版工程很多地方参考了 HandyControl 的实现。

集成

通过 NuGet 安装。

同时在 App.xaml 里配置引入 HandyControl 的主题等样式文件。

<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml" />
    <ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml" />
</ResourceDictionary.MergedDictionaries>

使用

安装了 HandyControl 后就可以创建 HandyControl 定义组件的实例,使用 HandyControl 定义的样式。

首先引入 HandyControl 的命名空间

xmlns:hc="https://handyorg.github.io/handycontrol" 

然后就可以创建组件,使用样式资源了。

// hc:InfoElement.Placeholder 为 HandyControl 对 TextBox 扩展的属性
<TextBox Text="{Binding InputText, UpdateSourceTrigger=PropertyChanged}"  hc:InfoElement.Placeholder="请输入内容,下方将显示预览" Style="{StaticResource TextBoxExtend}"/>

// TextBlockDefault 为 HandyControl 定义的样式
<TextBlock Text="{Binding InputText}" Style="{StaticResource TextBlockDefault}"></TextBlock>

Theme

主题样式的实现是参考了 HandyControl, 在上一步配置 App.xaml 时发现引入了 HandyControl 的 Theme 文件,然后深入看了下发现这种主题样式的实现很棒,于是就拿来主义了~

整体实现思路是 统一定义样式到 Theme.xaml 文件,然后引入到 App.xaml 的全局 ResourceDictionary 里。

// App.xaml
<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="pack://application:,,,/Resources/Themes/Theme.xaml" />
</ResourceDictionary.MergedDictionaries>
// Theme.xaml
<!--命名规则采用**类型+描述**,类型在前的目标是方便智能补全-->

<!-- Color全局定义 命名规则 Color+Hex -->
<Color x:Key="Color58C2DB">#58C2DB</Color>
<Color x:Key="ColorEAF4F6">#EAF4F6</Color>

<!-- Brush全局定义 命名规则 Brush+描述 -->
<SolidColorBrush o:Freeze="True" x:Key="BrushBackground" Color="{StaticResource Color58C2DB}"/>
<SolidColorBrush o:Freeze="True" x:Key="BrushPanel" Color="{StaticResource ColorEAF4F6}"/>
。。。
// MainWindow.xaml 调用 
<StackPanel Background="{StaticResource BrushBackground}">
</StackPanel>