概览
支持设计时预览通常对单元格本身的功能没有什么影响,但是好的设计时预览支持可以大幅提升单元格插件的设计时使用体验和效率。
在活字格中,设计时预览必须使用WPF技术实现,需要了解WPF窗体开发的一些知识,如XMAL,Binding等。
完善的设计时预览应该使得单元格在设计器中的样子和浏览器中尽可能的相似,并且在属性变更时,设计时预览也应该发生相应的变化。
根据经验,完善的设计时预览支持有时会占用开发单元格插件超过一半的时间,也是单元格插件开发过程中最困难的部分。如果是企业内部为了自用目的开发的单元格插件可以通过贴图,色块等方式适度简化单元格的设计时预览,以减少插件开发的时间,把更多的经历可以放到浏览器端的业务逻辑与用户交互上。
开始
在插件项目模板中找到 Designer\MyPluginCellTypeDesigner.cs 文件。默认代码如下。
public class MyPluginCellTypeDesigner : CellTypeDesigner<MyPluginCellType> { public override FrameworkElement GetDrawingControl(ICellInfo cellInfo, IDrawingHelper drawingHelper) { return new MyPluginCellTypeDrawingControl(this.CellType, cellInfo, drawingHelper); } }
通过重写 GetDrawingControl 方法,可以控制返回一个 WPF 的组件。模板工程中已经定义了一个 MyPluginCellTypeDrawingControl 的组件。代码在 Designer\DrawingControl\MyPluginCellTypeDrawingControl.xaml 中。一个WPF 组件包含两个文件
- MyPluginCellTypeDrawingControl.xaml 用于定义显示
- MyPluginCellTypeDrawingControl.xaml.cs 用于定义属性和逻辑
假设要开发一个显示进度的进度条单元格,那么首先如下修改 MyPluginCellTypeDrawingControl.xaml 文件。
<UserControl x:Class="MyPlugin.Designer.DrawingControl.MyPluginCellTypeDrawingControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="200"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="60*"></ColumnDefinition> <ColumnDefinition Width="40*"></ColumnDefinition> <ColumnDefinition Width="auto"></ColumnDefinition> </Grid.ColumnDefinitions> <Border Grid.ColumnSpan="2" CornerRadius="5" Height="10" Background="LightGray"></Border> <Border CornerRadius="5" Background="Green" Height="10"></Border> <TextBlock VerticalAlignment="Center" Grid.Column="2" Text="60%"></TextBlock> </Grid> </UserControl>
代码解释:
- 定义了一个网格布局控件(Grid),并定义了三列,第一列占60%宽度,第二列占40%宽度。最后一列自动适应内容
- 定义两个边框控件
- 第一个边框控件是灰色的表示背景,宽度跨了两列,高度10
- 第二个边框控件是绿色的表示值,占第一列,高度也是10
这样,一个进度条的设计时预览就完成了,在设计器中的效果如下:
现在的设计时预览有一个问题,就是所有表现都是固定的,接下来我们改进一下,使得设计时预览可以根据单元格的属性和值发生变化。
假设改进点如下:
- 添加进度颜色属性
- 添加是隐藏文本属性
- 进度条绿色块的长度随单元格的值变化,0的时候最短,100的时候填充满,文字显示进度值。
首先在 MyPluginCellType.cs 中添加相应的属性,代码如下
public class MyPluginCellType : CellType { [DisplayName("进度条颜色")] [ColorProperty] public string Color { get; set; } = "Green"; [DisplayName("隐藏文本")] public bool HideText { get; set; } }
找到 Designer\DrawingControl\MyPluginCellTypeDrawingControl.xaml.cs
使用以下代码替换原有代码
using GrapeCity.Forguncy.CellTypes; using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; namespace MyPlugin.Designer.DrawingControl { public partial class MyPluginCellTypeDrawingControl : UserControl { public MyPluginCellTypeDrawingControl(MyPluginCellType cellType, ICellInfo cellInfo, IDrawingHelper drawingHelper) { this.DataContext = new MyPluginCellTypeDrawingControlViewModel(cellType, cellInfo, drawingHelper); InitializeComponent(); } public class MyPluginCellTypeDrawingControlViewModel { MyPluginCellType _cellType; ICellInfo _cellInfo; IDrawingHelper _drawingHelper; double _progress = 0; public MyPluginCellTypeDrawingControlViewModel(MyPluginCellType cellType, ICellInfo cellInfo, IDrawingHelper drawingHelper) { _cellType = cellType; _cellInfo = cellInfo; _drawingHelper = drawingHelper; if (_cellInfo.Value != null && double.TryParse(_cellInfo.Value.ToString(), out var value)) { _progress = Math.Max(0, Math.Min(value, 100d)); // 把值调整到0到100之间 } } public string Text { get => _progress + "%"; } public Brush Color { get => _drawingHelper.GetBrush(_cellType.Color); } public Visibility TextVisiblity { get => _cellType.HideText ? Visibility.Collapsed : Visibility.Visible; } public GridLength FirstColumn { get => new GridLength(_progress, GridUnitType.Star); } public GridLength SecondColumn { get => new GridLength(100 - _progress, GridUnitType.Star); } } } }
MyPluginCellTypeDrawingControlViewModel 代码说明:
- 声明了 _progress 字段
- 通过 _cellInfo.Value 获取单元格的值,转为数字并把范围调整到 0 到 100 之间
- 声明了 Text 属性,返回百分百格式文本
- 声明了 Color属性, 通过 _drawingHelper.GetBrush 方法把文本颜色转成WPF可用的Brush类型
- 声明了 TextVisiblity, HideText 为True返回Visible,否则返回 Collapsed
- 声明了 FirstColumn SecondColumn,用于调整网格布局的列宽
再次修改 MyPluginCellTypeDrawingControl.xaml 文件
<UserControl x:Class="MyPlugin.Designer.DrawingControl.MyPluginCellTypeDrawingControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="200"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="{Binding FirstColumn}"></ColumnDefinition> <ColumnDefinition Width="{Binding SecondColumn}"></ColumnDefinition> <ColumnDefinition Width="auto"></ColumnDefinition> </Grid.ColumnDefinitions> <Border Grid.ColumnSpan="2" CornerRadius="5" Height="10" Background="LightGray"></Border> <Border CornerRadius="5" Background="{Binding Color}" Height="10"></Border> <TextBlock Visibility="{Binding TextVisiblity}" VerticalAlignment="Center" Grid.Column="2" Text="{Binding Text}"></TextBlock> </Grid> </UserControl>
注意,原来写死的列宽,颜色文本等,都使用了 {Binding 属性名} 的方式做了替换。这样,在WPF渲染的时候这些属性就会从 MyPluginCellTypeDrawingControl.xaml.cs 文件里的 MyPluginCellTypeDrawingControlViewModel 类上取值。实现动态效果
再次查看设计器中的效果,可以尝试修改颜色和单元格的值,看看有什么变化
总结
要实现设计时预览,修改以下两个文件
- MyPluginCellTypeDrawingControl.xaml.cs
- 用于添加可变属性,属性的值可以通过单元格插件的属性或单元格本身的属性计算得来。
- MyPluginCellTypeDrawingControl.xaml
- 用于通过 XAML 语法声明界面,通过 {Binding 属性} 语法实现动态效果