65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2017年2月15日

CPOL

7分钟阅读

viewsIcon

17803

downloadIcon

232

目前,所有主流的 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,包括偏移和重复的瓷砖),并使用 XAMLRoma 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.GeometryGroupSystem.Windows.Media.DrawingBrushX11.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,它利用其 ViewportTileMode 属性来实现重复的瓷砖,使用 LinearGradientBrush 来美化黑色棋盘格的外观,并使用其父 RectangleMargin 属性在棋盘周围实现边框(相对于父 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 直接定义在 RectangleFill 属性中,因为它只被使用/引用一次。

为了用一个画刷绘制背景和前景,必须将它们组合起来 - 这在 DrawingGroup drawinggroupBoard 中完成。

背景由一个简单的白色矩形 GeometryDrawing geometrydrawingWhiteBackground 实现,而前景 GeometryDrawing geometrydrawingBlackForeground 需要组合两个黑色矩形 - 这在 GeometryGroup geometrygroupBlackForeground 中完成。

为了完全填充(由 Rectangle rectangleBoard 定义的)国际象棋棋盘,DrawingBrush 必须在 x 和 y 方向上应用 4 次。DrawingBrushViewport 属性相对于要填充的 Rectangle 没有定义映射偏移(参见 Viewport="0, 0, ..."),并且相对于 Rectangle 的大小有一个 25% 的缩放(参见 Viewport="..., 0.25, 0.25")。DrawingBrushTileMode 属性启用了重复瓷砖的绘制。

后端代码 (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 日。

© . All rights reserved.