为 X11 和 Windows 编写 XAML 应用程序,绘制国际象棋棋盘以演示 DrawingBrush





5.00/5 (2投票s)
目前,所有主流的 Linux/Unix (X11) GUI 应用程序框架(GTK+、KDE)都不支持 XAML 应用程序开发。Moonlight 项目(包括 XAML 支持)已于 2012 年 5 月 29 日被放弃。本文回顾了一个利用 DrawingBrush(具有偏移和瓷砖功能)的 XAML 应用程序。
下载 XamlChessBoard_X11_32.zip 包含完整源代码和可执行文件的 Mono 解决方案
下载 XamlChessBoard_X11_64.zip 包含完整源代码和可执行文件的 Mono 解决方案
下载 XamlChessBoard_Win10.zip 包含完整源代码和可执行文件的 Visual Studio 2015 解决方案
引言
本文是一个案例研究,介绍如何使用 Roma Widget Set (Xrw) 编写一个基于 MVVM (Model View ViewModel) 设计模式的 X11/Windows (跨平台) 应用程序(利用 DrawingBrush,包括偏移和重复的瓷砖),并使用 XAML。 Roma Widget Set 是一个零依赖的 X11 GUI 应用程序框架(它仅需要免费的 Mono 标准安装程序和免费的 X11 发行版的库;它不特别需要 GNOME、KDE 或商业库),并且完全用 C# 实现。
本文是继《为 X11 编写 XAML 对话框应用程序》、《为 X11 编写 XAML 功能区应用程序》、《为 X11 编写具有海量数据绑定和零代码的 XAML 应用程序》、《为 X11 编写 XAML 计算器应用程序》、《为 X11 编写具有几何对象(形状)的 XAML 应用程序》、《为 X11 编写带 UserControls 的 XAML 应用程序》、《为 X11 和 Windows 编写 XAML 7 段 LCD 显示屏 UserControl》和《为 X11 和 Windows 编写 XAML 扫雷游戏》之后的作品。据我所知,这是在 Moonlight 被放弃后,使用 Xrw 进行 X11 应用程序开发的第一个尝试。
Roma Widget Set 和 XAML 实现都不是完整的。这个示例应用程序旨在作为更复杂的“概念验证”,并检查使用 XAML 创建基于 MVVM 设计模式的 X11/Windows (跨平台) 应用程序是否可能以及如何实现。
由于这是第九次尝试使用 XAML 进行 X11 应用程序开发并已成功,未来将继续发布关于使用 Roma Widget Set 在 X11 上使用 XAML 的相关文章。
背景
使用 XAML 进行 X11 应用程序开发的**动机**和一般**概念**已在《为 X11 编写 XAML 对话框应用程序》一文中进行了说明。
在 Xrw 发布 0.9 版本后,为该演示应用程序进行了一些重大增强(System.Windows.Media.GeometryGroup
、System.Windows.Media.DrawingBrush
和 X11.X11DrawingBrushInfo
),并修复了 Xrw XAML 包装器的一些错误。
焦点
由于之前的八篇“编写 XAML...”文章已经演示了多种 MVVM 技术,本文旨在演示使用 XAML 在 X11 上实现这一点
- 一个与 Windows 兼容的 DrawingBrush 可以轻松创建外观精美的国际象棋棋盘,利用绘制偏移、重复的瓷砖和颜色渐变。
使用代码
该示例应用程序是使用 Mono Develop 2.4.1 针对 Mono 2.8.1 在 OPEN SUSE 11.3 Linux 32 位 EN 和 GNOME 桌面上编写的。移植到任何旧版本或新版本应该都不是问题。示例应用程序的解决方案是使用 MONO/.NET 3.5 构建的。它包含两个项目(完整源代码可供下载)。
- XamlChessBoard 包含示例应用程序的源代码。
- XamlPreprocessor 包含 XAML 预处理器的源代码。
该示例应用程序还通过了 Mono Develop 3.0.6 在 OPEN SUSE 12.3 Linux 64 位 DE 和 GNOME 桌面、IceWM、TWM 和 Xfce 上针对 Mono 3.0.4 的测试。
32 位和 64 位解决方案之间的唯一区别是某些 X11 特定数据类型的定义,这与《使用 Mono Develop 编程 Xlib - 第 1 部分:低级别(概念验证)》一文中已描述的相同。
Xlib/X11 窗口处理基于 X11Wrapper 程序集版本 1.0(此解决方案中包含一个 1.0 版本候选库),它定义了 libX11.so 的函数原型、结构和类型。该程序集是为《使用 Mono Develop 编程 Xlib - 第 1 部分:低级别(概念验证)》项目开发的,并在《编程 Roma Widget Set (C# X11) - 一个零依赖的 GUI 应用程序框架 - 基础》项目中得到改进。
GUI 框架基于 Xrw 程序集版本 1.0(此解决方案中包含一个 1.0 版本候选库),它定义了 XAML 代码中使用的控件/小部件及其包装器类(这些类应尽可能接近 Microsoft® 原版)。该程序集是在《编程 Roma Widget Set (C# X11) - 一个零依赖的 GUI 应用程序框架 - 基础》项目中开发的。
示例应用程序实现了一个 DrawingBrush drawingbrushBoard,它利用其 Viewport 和 TileMode 属性来实现重复的瓷砖,使用 LinearGradientBrush 来美化黑色棋盘格的外观,并使用其父 Rectangle 的 Margin 属性在棋盘周围实现边框(相对于父 Canvas 进行偏移)。示例应用程序的 Windows Visual Studio 2015 项目完全基于 Purushottam Rathore 在其文章《WPF 中的 DrawingBrush》中的源代码(非常感谢他提供这个演示 DrawingBrush 的绝妙主意)。Linux/Unix (X11) Mono 项目也源自此源代码。 | ![]() |
建议:要使用 MonoDevelop 的类库文档快捷键 (F1),必须安装“mono-tools”软件包。
示例应用程序的图片展示了国际象棋棋盘在多个平台上的效果。
第一张图片显示了示例应用程序在 OPEN SUSE 11.3 Linux 32 位 EN 和 GNOME 桌面上的样子。
第二张图片显示了示例应用程序在 OPEN SUSE 12.3 Linux 64 位 DE 和 Xfce 上的样子。
第三张图片展示了该示例应用程序在 Windows® 10 64 位版本上的效果。
应用程序窗口使用 System.Windows.Controls.Canvas
作为根布局管理器。它还定义了子 System.Windows.Shapes.Rectangle
及其用于填充矩形的 System.Windows.Media.DrawingBrush
。
布局由矩形的 Margin
属性定义。绘制画刷大小为 100px * 100px,而矩形的宽度和高度为 400px * 400px。因此,绘制画刷必须在 x 方向和 y 方向上应用 4 次才能完全填充矩形。
X11 和 Windows® 10 版本的示例应用程序之间没有功能上的区别,它们共享相同的 XAML 代码(除了边距值),并且没有代码隐藏(因此这里没有区别)。
逐步演示
主视图文件上下文
XAML (MainWindow.xaml)
这是 XAML 文件的完整代码(X11 32 位 MonoDevelop 解决方案)
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ext="clr-namespace:System.Windows.ExtControls"
x:Class="XamlChessBoard.MainWindow"
Name="DigiClock" Title="Chess Board"
Height="500" Width="500" Icon="XrwIcon16.bmp"
Background="#FFDDDDDD">
<Canvas Name="canvasRoot" Background="SkyBlue">
<Rectangle Name="rectangleBoard" Width="400" Height="400" Margin="50,45,40,40">
<Rectangle.Fill>
<DrawingBrush x:Name="drawingbrushBoard" Viewport="0,0,0.25,0.25" TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup x:Name="drawinggroupBoard">
<GeometryDrawing x:Name="geometrydrawingWhiteBackground" Brush="White">
<GeometryDrawing.Geometry>
<RectangleGeometry x:Name="geometryWhiteBackground" Rect="0,0,100,100" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing x:Name="geometrydrawingBlackForeground">
<GeometryDrawing.Geometry>
<GeometryGroup x:Name="geometrygroupBlackForeground">
<RectangleGeometry x:Name="rectanglegeometryBlack1" Rect="0,0,50,50" />
<RectangleGeometry x:Name="rectanglegeometryBlack2" Rect="50,50,50,50" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Brush>
<LinearGradientBrush>
<GradientStop Offset="0.0" Color="Black" />
<GradientStop Offset="1.0" Color="Gray" />
</LinearGradientBrush>
</GeometryDrawing.Brush>
</GeometryDrawing>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>
</Canvas>
</Window
示例应用程序没有任何资源 - DrawingBrush
直接定义在 Rectangle
的 Fill
属性中,因为它只被使用/引用一次。
为了用一个画刷绘制背景和前景,必须将它们组合起来 - 这在 DrawingGroup
drawinggroupBoard 中完成。
背景由一个简单的白色矩形 GeometryDrawing
geometrydrawingWhiteBackground 实现,而前景 GeometryDrawing
geometrydrawingBlackForeground 需要组合两个黑色矩形 - 这在 GeometryGroup
geometrygroupBlackForeground 中完成。
为了完全填充(由 Rectangle
rectangleBoard 定义的)国际象棋棋盘,DrawingBrush
必须在 x 和 y 方向上应用 4 次。DrawingBrush
的 Viewport
属性相对于要填充的 Rectangle
没有定义映射偏移(参见 Viewport="0, 0, ..."
),并且相对于 Rectangle
的大小有一个 25% 的缩放(参见 Viewport="..., 0.25, 0.25"
)。DrawingBrush
的 TileMode
属性启用了重复瓷砖的绘制。
后端代码 (MainWindow.xaml.cs)
主视图对应的 C# 代码文件是 MainWindow.xaml.cs
,它只包含最少的代码。
namespace XamlChessBoard
{
/// <summary>Interaction logic for MainWindow.xaml</summary>
/// <remarks>Idea based on article
/// <see cref="http://www.c-sharpcorner.com/uploadfile/prathore/drawingbrush-in-wpf/"/>.</remarks>
public partial class MainWindow : XrwXAML.Window
{
public MainWindow()
: base (-1, -1)
{
InitializeComponent();
}
}
}
主视图模型文件上下文
主视图没有 ModelView,因为不需要 Model。
主模型文件上下文
主视图没有 Model,因为没有数据需要处理。
关注点
这是另一个适用于 X11 的 XAML 应用程序,与 Microsoft® 完全兼容,展示了这种方法的优点(与使用 GTK+ 或 KDE 的实现相比):100% 跨平台兼容的 GUI 定义,以及创建 GUI 时代码行的节省。
使用 DrawingBrush
提供了一种创建精美外观的非常简单的方法,这可以应用于 X11 和 Windows(跨平台)。
历史
本文的第一个版本发布于 2017 年 2 月 12 日。