【WPF】xamlと同等の内容をC#のコードで書いた例

By | 2011年9月7日

xamlと同等の内容をC#のコードで書いてみる。
今回のサンプルとなるのは以下のようなプログラムである。

画面の真ん中にGeometryで描いた画像が配置してある。この画像にはRenderTransformがセットしてあり、
回転値は下に配置したスライダーの値にバインディングされている。

それではまず、このプログラムをxamlで書いた場合はどうなるかを示す。

MainWindow.xaml

<Window x:Class="XamlCodeLesson_xaml.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition Height="24"></RowDefinition>
        </Grid.RowDefinitions>
        <!-- 真ん中に配置された図形 -->
        <Path HorizontalAlignment="Center" VerticalAlignment="Center" Stroke="Blue">
            <Path.Data>
                <GeometryGroup>
                    <EllipseGeometry Center="30 30" RadiusX="30" RadiusY="30"></EllipseGeometry>
                    <EllipseGeometry Center="60 30" RadiusX="30" RadiusY="30"></EllipseGeometry>
                </GeometryGroup>
            </Path.Data>
            <Path.RenderTransform>
                <RotateTransform Angle="{Binding ElementName=slider,Path=Value}" CenterX="45" CenterY="30"></RotateTransform>
            </Path.RenderTransform>
        </Path>
        <!-- スライダー -->
        <Slider Name="slider" Grid.Row="1" Minimum="0" Maximum="359" TickFrequency="0.1"></Slider>
    </Grid>
</Window>

ここまでで、一切C#のコードは書いていない。
以上がxamlで書いた場合の全コードとなる。

それでは次に、C#のコードで書いた場合はどうなるかを示す。C#で書く場合、VisualStudioが用意したWPFアプリケーションテンプレートのxamlに一箇所だけ追記した。そのxamlは以下のようになる。

MainWindow.xaml

<Window x:Class="XamlCodeLesson_code.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid Name="grid">
        
    </Grid>
</Window>

あらかじめ配置されているGridに”grid”と名前を付けた。C#のコードからアクセスできるようにするためにこうする必要がある。
そして、C#のコードは以下のようになる。

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

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

            grid.RowDefinitions.Add(new RowDefinition());
            grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(24.0d) });

            // パスの生成
            Path path = new Path()
            {
                HorizontalAlignment = System.Windows.HorizontalAlignment.Center,
                VerticalAlignment = System.Windows.VerticalAlignment.Center,
                Stroke = Brushes.Blue,
                Data = new GeometryGroup()
                {
                    Children = new GeometryCollection()
                    {
                        new EllipseGeometry()
                        {
                            Center = new Point(30.0d,30.0d),
                            RadiusX = 30.0d,
                            RadiusY = 30.0d
                        },
                        new EllipseGeometry()
                        {
                            Center = new Point(60.0d, 30.0d),
                            RadiusX = 30.0d,
                            RadiusY = 30.0d
                        }
                    }
                },
                RenderTransform = new RotateTransform()
                {
                    CenterX=45.0d,
                    CenterY=30.0d
                }
            };

            grid.Children.Add(path);


            // スライダーの生成
            Slider slider = new Slider()
            {
                Minimum = 0.0d,
                Maximum = 353.0d,
                TickFrequency = 0.1d
            };

            // 添付プロパティをセット
            Grid.SetRow(slider, 1);
            grid.Children.Add(slider);


            // バインディングをセット
            BindingOperations.SetBinding(
                path.RenderTransform,
                RotateTransform.AngleProperty,
                new Binding("Value")
                {
                    // ElementNameではなく、
                    // ソースとなるオブジェクトの参照をセットする必要があるようだ
                    Source = slider
                }
            );
        }
    }
}

注意が必要なのは、xamlと同じ感覚で、82行目でSourceではなくElementNameを指定してしまうとバインディングが上手く働かないということである。C#でバインディングのコードを書くときはSourceプロパティにソースとなるオブジェクトの参照をセットする必要があるようだ。
以上がC#で書いた場合の全コードとなる。
2つのコードを比べてみると、やはりWPFではUIはxamlで書いた方がすっきりすることが分かる。xamlに慣れ、なるべくUIはxamlで書くべきだろう。
しかし、時にはC#のコードでUIを書く必要に迫られる場合もあるので、C#での書き方も頭に留めておいた方が良いと思う。
今回、C#のコードでややこしいと思ったのは、添付プロパティのセットの方法とバインディングの定義の仕方だった。


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です