WPFで Visioのようなフローチャートソフトを開発する

WPFで Visioのようなフローチャートソフトを開発する

フローチャートを描きたいとき、多くのソフトウェアはライセンスキーが必要だったり、会員登録が必要だったりします。そこで、自分でフローチャートソフトを作れないかと考えました。

最終更新 2022/02/27 15:04
Alan.hsiang
読了目安 13 分
カテゴリ
WPF
タグ
.NET WPF Visio

フローチャートを描きたいと思ったとき、多くのソフトウェアがライセンスキーを必要としたり、会員登録が必要だったりすることに気づきます。そこで、自分でフローチャートソフトウェアを作れないかと考えました。この記事では、簡単なサンプルを通して、WPFを使って自分だけのフローチャートソフトウェアを作る方法を説明します。あくまで学習と共有のためのものであり、不十分な点があればご指摘ください。

関連知識

このサンプルは主にWPF技術を使用して開発されています。関連する知識は以下の通りです。

  1. WPFの描画機能:矩形、直線などの図形に関する技術。
  2. Thumbコントロール:ユーザーが自由にドラッグできるコントロール。サンプルで使用する移動可能な図形コントロールは、すべてThumbコントロールを継承しています。

Thumbコントロールの概要

Thumbコントロールは、WPFが提供するユーザーがドラッグできるコントロールです。デフォルトではツールボックスに含まれていないため、手動で追加する必要があります。以下の手順で行います。

ツールボックス → 全般 → 右クリック → アイテムの選択 を開き、[ツールボックスアイテムの選択]ダイアログを表示します。以下のようになります。

[ツールボックスアイテムの選択]ページで、WPFコンポーネント → Thumbを選択 → OKボタンをクリックします。以下のようになります。

追加が成功すると、ツールボックスからページにドラッグできるようになります。以下のようになります。

Thumbコントロールの概要は以下の通りです。

namespace System.Windows.Controls.Primitives
{
    //
    // 要約:
    //     ユーザーがドラッグできるコントロールを表します。
    [DefaultEvent("DragDelta")]
    [Localizability(LocalizationCategory.NeverLocalize)]
    public class Thumb : Control
    {
        //
        // 要約:
        //     System.Windows.Controls.Primitives.Thumb.DragStarted ルーティングイベントを識別します。
        //
        // 戻り値:
        //     System.Windows.Controls.Primitives.Thumb.DragStarted ルーティングイベントの識別子。
        public static readonly RoutedEvent DragStartedEvent;
        //
        // 要約:
        //     System.Windows.Controls.Primitives.Thumb.DragDelta ルーティングイベントを識別します。
        //
        // 戻り値:
        //     System.Windows.Controls.Primitives.Thumb.DragDelta ルーティングイベントの識別子。
        public static readonly RoutedEvent DragDeltaEvent;
        //
        // 要約:
        //     System.Windows.Controls.Primitives.Thumb.DragCompleted ルーティングイベントを識別します。
        //
        // 戻り値:
        //     System.Windows.Controls.Primitives.Thumb.DragCompleted ルーティングイベントの識別子。
        public static readonly RoutedEvent DragCompletedEvent;
        //
        // 要約:
        //     System.Windows.Controls.Primitives.Thumb.IsDragging 依存関係プロパティを識別します。
        //
        // 戻り値:
        //     System.Windows.Controls.Primitives.Thumb.IsDragging 依存関係プロパティの識別子。
        public static readonly DependencyProperty IsDraggingProperty;

        //
        // 要約:
        //     System.Windows.Controls.Primitives.Thumb クラスの新しいインスタンスを初期化します。
        public Thumb();

        //
        // 要約:
        //     System.Windows.Controls.Primitives.Thumb コントロールが論理フォーカスを持ち、マウスをキャプチャし、マウスの左ボタンが押されているかどうかを取得します。
        //
        // 戻り値:
        //     System.Windows.Controls.Primitives.Thumb コントロールがフォーカスとマウスキャプチャを持っている場合は true。それ以外の場合は false。既定値は
        //     false。
        [Bindable(true)]
        [Browsable(false)]
        [Category("Appearance")]
        public bool IsDragging { get; protected set; }

        //
        // 要約:
        //     System.Windows.Controls.Primitives.Thumb コントロールが論理フォーカスとマウスキャプチャを受け取ったときに発生します。
        [Category("Behavior")]
        public event DragStartedEventHandler DragStarted;
        //
        // 要約:
        //     マウスの位置が変更されたときに 1 回以上発生します。 System.Windows.Controls.Primitives.Thumb コントロールが論理フォーカスとマウスキャプチャを持っているときに発生します。
        [Category("Behavior")]
        public event DragDeltaEventHandler DragDelta;
        //
        // 要約:
        //     System.Windows.Controls.Primitives.Thumb コントロールがマウスキャプチャを失ったときに発生します。
        [Category("Behavior")]
        public event DragCompletedEventHandler DragCompleted;

        //
        // 要約:
        //     System.Windows.Controls.Primitives.Thumb のドラッグ操作をキャンセルします。
        public void CancelDrag();
        //
        // 要約:
        //     System.Windows.Controls.Primitives.Thumb コントロールの System.Windows.Automation.Peers.AutomationPeer を作成します。
        //
        // 戻り値:
        //     System.Windows.Controls.Primitives.Thumb コントロールの System.Windows.Automation.Peers.ThumbAutomationPeer。
        protected override AutomationPeer OnCreateAutomationPeer();
        //
        // 要約:
        //     System.Windows.Controls.Primitives.Thumb.IsDragging プロパティの値の変更に応答します。
        //
        // パラメーター:
        //   e:
        //     イベントデータ。
        protected virtual void OnDraggingChanged(DependencyPropertyChangedEventArgs e);
        //
        // 要約:
        //     System.Windows.ContentElement.MouseLeftButtonDown イベントのクラス処理を提供します。
        //
        // パラメーター:
        //   e:
        //     イベントデータ。
        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e);
        //
        // 要約:
        //     System.Windows.ContentElement.MouseLeftButtonUp イベントのクラス処理を提供します。
        //
        // パラメーター:
        //   e:
        //     イベントデータ。
        protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e);
        //
        // 要約:
        //     System.Windows.UIElement.MouseMove イベントのクラス処理を提供します。
        //
        // パラメーター:
        //   e:
        //     イベントデータ。
        protected override void OnMouseMove(MouseEventArgs e);
    }
}

上記の概要から、Thumbコントロールは3つのイベントを提供していることがわかります。

  • ドラッグ開始イベント: public event DragStartedEventHandler DragStarted;
  • ドラッグ中イベント: public event DragDeltaEventHandler DragDelta;
  • ドラッグ完了イベント: public event DragCompletedEventHandler DragCompleted;

Thumbコントロールのサンプル

まず、ウィンドウページにThumbコントロールを追加し、3つのイベントをそれぞれ追加します。以下のようになります。

<Window
  x:Class="DemoVisio.MainWindow1"
  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:DemoVisio"
  mc:Ignorable="d"
  Title="Thumbサンプル"
  Height="450"
  Width="800"
>
  <Canvas>
    <Thumb
      x:Name="thumb"
      Canvas.Left="0"
      Canvas.Top="0"
      Height="100"
      Width="100"
      DragStarted="thumb_DragStarted"
      DragDelta="thumb_DragDelta"
      DragCompleted="thumb_DragCompleted"
    />
  </Canvas>
</Window>

次に、3つのイベントにコードを追加します。特に重要なのはDragDeltaイベントです。以下のようになります。

namespace DemoVisio
{
    /// <summary>
    /// MainWindow1.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow1 : Window
    {
        public MainWindow1()
        {
            InitializeComponent();
        }

        private void thumb_DragStarted(object sender, DragStartedEventArgs e)
        {
            // ドラッグ開始
        }

        /// <summary>
        /// ドラッグ中
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void thumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
        {
            Thumb myThumb = (Thumb)sender;
            double nTop = Canvas.GetTop(myThumb) + e.VerticalChange;
            double nLeft = Canvas.GetLeft(myThumb) + e.HorizontalChange;
            Canvas.SetTop(myThumb, nTop);
            Canvas.SetLeft(myThumb, nLeft);
        }

        private void thumb_DragCompleted(object sender, DragCompletedEventArgs e)
        {
            // ドラッグ完了
        }
    }
}

注意点: XAMLでは、Thumbは必ずCanvasレイアウトコンテナ内に配置し、Canvas.Left="0"Canvas.Top="0" の2つのプロパティを設定する必要があります。設定しないと値がNaNになり、ドラッグできません。

デフォルトでは、Thumbコントロールはシンプルな四角形として表示されます。以下のようになります。

ドラッグ可能なコントロールの基底クラス

このサンプルでは、フローチャートに複数のコントロール(円、矩形、線など)が必要であり、それぞれに DragStartedDragDeltaDragCompleted の3つのイベントを実装するのは非効率的です。そこで、基底クラス ThumbControl を定義し、共通の実装を提供します。具体的には以下の通りです。

namespace DemoVisio
{
    public class ThumbControl : Thumb
    {
        /// <summary>
        /// 入力が可能かどうか
        /// </summary>
        public bool IsEnableInput { get { return (bool)GetValue(IsEnableInputProperty); } set { SetValue(IsEnableInputProperty, value); } }

        /// <summary>
        /// 依存関係プロパティ
        /// </summary>
        public static readonly DependencyProperty IsEnableInputProperty = DependencyProperty.Register("IsEnableInput", typeof(bool), typeof(ThumbControl));

        public ThumbControl() : base()
        {
            this.DragStarted += ThumbControl_DragStarted;
            this.DragDelta += ThumbControl_DragDelta;
            this.DragCompleted += ThumbControl_DragCompleted;
            this.MouseDoubleClick += ThumbControl_MouseDoubleClick;
            this.IsKeyboardFocusedChanged += ThumbControl_IsKeyboardFocusedChanged;
        }

        public void SetIsEnableInput(bool flag)
        {
            this.IsEnableInput = flag;
        }

        /// <summary>
        /// キーボードフォーカスの変化
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ThumbControl_IsKeyboardFocusedChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            this.IsEnableInput = this.IsKeyboardFocused;
        }

        /// <summary>
        /// ダブルクリックイベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ThumbControl_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            this.IsEnableInput = true;
        }

        private void ThumbControl_DragStarted(object sender, DragStartedEventArgs e)
        {
            // 移動開始
        }

        private void ThumbControl_DragDelta(object sender, DragDeltaEventArgs e)
        {
            Thumb myThumb = (Thumb)sender;
            double nTop = Canvas.GetTop(myThumb) + e.VerticalChange;
            double nLeft = Canvas.GetLeft(myThumb) + e.HorizontalChange;
            Canvas.SetTop(myThumb, nTop);
            Canvas.SetLeft(myThumb, nLeft);
        }

        private void ThumbControl_DragCompleted(object sender, DragCompletedEventArgs e)
        {
            // 移動終了
        }
    }
}

具体的な図形コントロール

基底クラスをカプセル化した後、他のコントロールはそれを基に使用でき、ControlTemplate によって異なる形状を表現します。以下の通りです。

1. 矩形(四角形)

フローチャートでは、矩形は通常「処理」を表します。実装コードは以下の通りです。

<UserControl
  x:Class="DemoVisio.SquareControl"
  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"
  xmlns:local="clr-namespace:DemoVisio"
  mc:Ignorable="d"
  d:DesignHeight="450"
  d:DesignWidth="800"
>
  <Canvas>
    <local:ThumbControl
      x:Name="s"
      BorderThickness="1"
      Canvas.Top="0"
      Canvas.Left="0"
      Width="100"
      Height="60"
      Background="AliceBlue"
    >
      <Thumb.Template>
        <ControlTemplate>
          <Border
            Width="{Binding ElementName=s, Path=Width}"
            Height="{Binding ElementName=s, Path=Height}"
            BorderBrush="Black"
            Background="{Binding ElementName=s, Path=Background}"
            BorderThickness="{Binding ElementName=s, Path=BorderThickness}"
            Padding="2"
          >
            <TextBox
              Background="{Binding ElementName=s, Path=Background}"
              BorderThickness="0"
              VerticalAlignment="Center"
              IsEnabled="{Binding ElementName=s, Path=IsEnableInput}"
              MinLines="3"
              MaxLines="3"
              HorizontalContentAlignment="Center"
              VerticalContentAlignment="Center"
            ></TextBox>
          </Border>
        </ControlTemplate>
      </Thumb.Template>
    </local:ThumbControl>
  </Canvas>
</UserControl>

2. 円

フローチャートでは、円は通常「開始」または「終了」を表します。以下の通りです。

<UserControl
  x:Class="DemoVisio.CircleControl"
  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"
  xmlns:local="clr-namespace:DemoVisio"
  mc:Ignorable="d"
  d:DesignHeight="450"
  d:DesignWidth="800"
>
  <Canvas>
    <local:ThumbControl
      x:Name="s"
      Canvas.Top="0"
      Canvas.Left="0"
      Width="60"
      Height="60"
      Background="AliceBlue"
      BorderThickness="1"
    >
      <local:ThumbControl.Template>
        <ControlTemplate>
          <Grid>
            <Border
              Width="{Binding Width}"
              Height="{Binding Height}"
              CornerRadius="30"
              BorderThickness="{Binding ElementName=s, Path=BorderThickness}"
              BorderBrush="Black"
              Background="{Binding ElementName=s, Path=Background}"
            >
              <TextBox
                VerticalAlignment="Center"
                HorizontalContentAlignment="Center"
                VerticalContentAlignment="Center"
                MaxLines="2"
                MinLines="1"
                Width="{Binding Width}"
                Height="{Binding Height}"
                Background="{Binding ElementName=s, Path=Background}"
                BorderThickness="0"
                IsEnabled="{Binding ElementName=s, Path=IsEnableInput}"
              ></TextBox>
            </Border>
          </Grid>
        </ControlTemplate>
      </local:ThumbControl.Template>
    </local:ThumbControl>
  </Canvas>
</UserControl>

3. 菱形

フローチャートでは、菱形は通常「選択」を表し、プログラムの真理値を表現します。以下の通りです。

<UserControl
  x:Class="DemoVisio.RhombusControl"
  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"
  xmlns:local="clr-namespace:DemoVisio"
  mc:Ignorable="d"
  d:DesignHeight="450"
  d:DesignWidth="800"
>
  <Canvas>
    <local:ThumbControl
      x:Name="s"
      Canvas.Left="0"
      Canvas.Top="0"
      Width="80"
      Height="80"
      Background="AliceBlue"
      BorderThickness="1"
    >
      <Thumb.Template>
        <ControlTemplate>
          <Border
            Width="{Binding ElementName=s, Path=Width}"
            Height="{Binding ElementName=s, Path=Height}"
            BorderBrush="Black"
            Background="{Binding ElementName=s, Path=Background}"
            BorderThickness="{Binding ElementName=s, Path=BorderThickness}"
            Padding="1"
          >
            <TextBox
              Background="{Binding ElementName=s, Path=Background}"
              BorderThickness="0"
              VerticalAlignment="Center"
              IsEnabled="{Binding ElementName=s, Path=IsEnableInput}"
              Width="50"
              Height="50"
              HorizontalContentAlignment="Center"
              VerticalContentAlignment="Center"
            >
              <TextBox.RenderTransform>
                <RotateTransform
                  CenterX="25"
                  CenterY="25"
                  Angle="-45"
                ></RotateTransform>
              </TextBox.RenderTransform>
            </TextBox>
          </Border>
        </ControlTemplate>
      </Thumb.Template>
      <Thumb.RenderTransform>
        <TransformGroup>
          <RotateTransform
            CenterX="40"
            CenterY="40"
            Angle="45"
          ></RotateTransform>
          <ScaleTransform
            CenterX="40"
            CenterY="40"
            ScaleX="0.8"
          ></ScaleTransform>
          <TranslateTransform X="10" Y="15"></TranslateTransform>
        </TransformGroup>
      </Thumb.RenderTransform>
    </local:ThumbControl>
  </Canvas>
</UserControl>

4. 直線

フローチャートでは、直線は通常2つの処理間の接続を表します。以下の通りです。

<UserControl
  x:Class="DemoVisio.LineArrowControl"
  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"
  xmlns:local="clr-namespace:DemoVisio"
  mc:Ignorable="d"
  d:DesignHeight="450"
  d:DesignWidth="800"
>
  <Canvas>
    <local:ThumbControl
      x:Name="s"
      Canvas.Left="0"
      Canvas.Top="0"
      Width="100"
      Height="100"
      Background="AliceBlue"
      IsEnableInput="False"
    >
      <local:ThumbControl.Template>
        <ControlTemplate>
          <Grid>
            <Line
              X1="0"
              Y1="0"
              X2="0"
              Y2="100"
              Stroke="Black"
              StrokeThickness="2"
              HorizontalAlignment="Center"
            >
            </Line>
            <Line
              X1="-5"
              Y1="90"
              X2="1"
              Y2="100"
              StrokeThickness="2"
              Stroke="Black"
              HorizontalAlignment="Center"
            ></Line>
            <Line
              X1="8"
              Y1="90"
              X2="3"
              Y2="100"
              StrokeThickness="2"
              Stroke="Black"
              HorizontalAlignment="Center"
            ></Line>
            <TextBox
              VerticalAlignment="Center"
              Height="30"
              HorizontalContentAlignment="Center"
              BorderThickness="0"
              VerticalContentAlignment="Center"
              MinLines="1"
              MaxLines="2"
              IsEnabled="{Binding ElementName=s, Path=IsEnableInput}"
              Opacity="0"
              Visibility="{Binding ElementName=s, Path=IsEnableInput}"
            ></TextBox>
          </Grid>
        </ControlTemplate>
      </local:ThumbControl.Template>
    </local:ThumbControl>
  </Canvas>
</UserControl>

メインウィンドウ

メインウィンドウはフローチャートを描画するためのもので、左側にコントロール一覧、右側にレイアウトコンテナを配置します。以下の通りです。

<Window
  x:Class="DemoVisio.MainWindow"
  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:DemoVisio"
  mc:Ignorable="d"
  Title="フローチャート"
  Height="800"
  Width="800"
  MouseDown="Window_MouseDown"
  Loaded="Window_Loaded"
>
  <Window.Resources>
    <Style TargetType="TextBlock">
      <Setter Property="HorizontalAlignment" Value="Center"></Setter>
    </Style>
  </Window.Resources>
  <Grid ShowGridLines="True">
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="Auto" MinWidth="150"></ColumnDefinition>
      <ColumnDefinition Width="*"></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <StackPanel Grid.Column="0" x:Name="left" Orientation="Vertical">
      <Rectangle
        Width="80"
        Height="50"
        Fill="AliceBlue"
        Stroke="Black"
        Margin="5"
        x:Name="rectangle"
        MouseLeftButtonDown="rectangle_MouseLeftButtonDown"
      ></Rectangle>
      <TextBlock Text="矩形"></TextBlock>
      <Rectangle
        Width="100"
        Height="100"
        Fill="AliceBlue"
        Stroke="Black"
        Margin="5"
        x:Name="rhombus"
        MouseLeftButtonDown="rhombus_MouseLeftButtonDown"
      >
        <Rectangle.RenderTransform>
          <TransformGroup>
            <RotateTransform
              CenterX="50"
              CenterY="50"
              Angle="45"
            ></RotateTransform>
            <ScaleTransform
              CenterX="50"
              CenterY="50"
              ScaleX="0.5"
              ScaleY="0.7"
            ></ScaleTransform>
          </TransformGroup>
        </Rectangle.RenderTransform>
      </Rectangle>
      <TextBlock Text="菱形" Margin="0,5"></TextBlock>
      <Line
        X1="0"
        Y1="0"
        X2="0"
        Y2="80"
        Stroke="Black"
        StrokeThickness="2"
        HorizontalAlignment="Center"
        Margin="5"
        x:Name="line"
        MouseLeftButtonDown="line_MouseLeftButtonDown"
      ></Line>
      <TextBlock Text="直線"></TextBlock>
      <Ellipse
        Width="60"
        Height="60"
        Fill="AliceBlue"
        Stroke="Black"
        Margin="5"
        x:Name="circle"
        MouseLeftButtonDown="circle_MouseLeftButtonDown"
      ></Ellipse>
      <TextBlock Text="円"></TextBlock>
    </StackPanel>
    <Canvas Grid.Column="1" x:Name="right"> </Canvas>
  </Grid>
</Window>

左側の基本コントロールをクリックすると、右側のコンテナに新しいコントロールが生成されます。以下の通りです。

namespace DemoVisio
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        /// <summary>
        /// コントロールリスト
        /// </summary>
        private List<Control> rightControls = new List<Control>();

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_MouseDown(object sender, MouseButtonEventArgs e)
        {
            //this.Focus();
            //this.one.SetIsEnableInput(false);
            foreach (var control in this.right.Children)
            {
                var thumb = control as ThumbControl;
                if (thumb != null)
                {
                    thumb.SetIsEnableInput(false);
                }
            }
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            var width = this.right.ActualWidth;
            var height = this.right.ActualHeight;

            int x = 0;
            int y = 0;
            // 横線
            while (y < height)
            {
                Line line = new Line();
                line.X1 = x;
                line.Y1 = y;
                line.X2 = width;
                line.Y2 = y;
                line.Stroke = Brushes.LightGray;
                line.StrokeThickness = 1;
                this.right.Children.Add(line);
                y = y + 10;
            }
            // 再初期化
            x = 0;
            y = 0;
            // 縦線
            while (x < width)
            {
                Line line = new Line();
                line.X1 = x;
                line.Y1 = y;
                line.X2 = x;
                line.Y2 = height;
                line.Stroke = Brushes.LightGray;
                line.StrokeThickness = 1;
                this.right.Children.Add(line);
                x = x + 10;
            }
        }

        private void rectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            SquareControl squareControl = new SquareControl();
            this.right.Children.Add(squareControl);
        }

        private void rhombus_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            RhombusControl rhombusControl = new RhombusControl();
            this.right.Children.Add(rhombusControl);
        }

        private void line_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            LineArrowControl lineArrowControl = new LineArrowControl();
            this.right.Children.Add(lineArrowControl);
        }

        private void circle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            CircleControl circleControl = new CircleControl();
            this.right.Children.Add(circleControl);
        }
    }
}

サンプルスクリーンショット

サンプルの基本スクリーンショットは以下の通りです。

備考

上記のサンプルは基本的なものであり、機能は完全ではありません。あくまで抛砖引玉(参考として提供する)の意図であり、共に学び、共に進歩することを目的としています。皆様の参考になれば幸いです。

賀新郎·九日

【作者】劉克庄 【朝代】宋
湛湛長空黒。更那堪、斜風細雨、乱愁如織。
老眼平生空四海、頼有高樓百尺。
看浩蕩、千崖秋色。
白髪書生神州涙、尽淒涼、不向牛山滴。
追往事、去無跡。

少年自負凌雲筆。到而今、春華落尽、満懐蕭瑟。
常恨世人新意少、愛説南朝狂客。
把破帽、年年拈出。
若対黄花孤負酒、怕黄花、也笑人岑寂。
鴻北去、日西匿。
さらに探索

関連読書

その他の記事
同じカテゴリ / 同じタグ 2025/09/13

WPF から Avalonia への移行シリーズ:なぜ WPF プログラムを Avalonia に移行しなければならないのか

過去数年間、当社の上位機ソフトウェアは主に WPF と WinForm で開発されてきました。これらの技術は Windows プラットフォームで非常に便利であり、小規模試作から現在の規模拡大による納品まで、私たちを支えてきました。しかし、ビジネスの発展や顧客ニーズの変化に伴い、単一の Windows テクノロジースタックは私たちが必ず乗り越えなければならない壁となってきました。

続きを読む
同じカテゴリ / 同じタグ 2025/01/26

WPF カスタムXMLファイルによる国際化

この記事では、WPFプログラムでカスタムXMLファイルを使用して国際化を実現する方法について詳しく説明します。必要なNuGetパッケージのインストール、言語リストの動的取得、言語の動的切り替え、コードおよびXAMLインターフェースでの翻訳文字列の使用などを含み、ソースコードのリンクも提供し、開発者がWPFアプリケーションの国際化を簡単に実装できるように支援します。

続きを読む