レガシーコードからの脱却

レガシーな職場でも独学でどうにか頑張っていくブログです。

【お勉強記録】WPFデータバインディング1

現在の職場においてもWPFを使って書かれたソフトがあり、ときどき触ります。

その職場で触るコードなのですが、データバインディングを行わず、 コードビハインドコード内で、直接コントロールのプロパティを変更しております…。orz

データバインディング

xaml側でのデータバインドは{Binding}を使います。

<StackPanel>
        <TextBlock Name="tbName" Text="{Binding ElementName=txtName,Path=Text}"></TextBlock>
        <TextBox Name="txtName"></TextBox>
</StackPanel>

Bindingはコード側でも実装することができます。

<StackPanel>
        <TextBlock Name="tbName"></TextBlock>
        <TextBox Name="txtName"></TextBox>        
</StackPanel>
protected void InitializeDataBinding()
{
    Binding binding = new Binding();
    binding.Source = this.txtName;
    binding.Path = new PropertyPath("Text");
    tbName.SetBinding(TextBlock.TextProperty, binding);
}

CLRオブジェクトのバインディング

バインディングソースには自分で作ったクラスオブジェクトも指定可能です。

ここではユーザークラスのオブジェクトのバインディングの例でやってみました。

ユーザークラス

using System;

namespace _0721Study
{
    public class User
    {
        public User() { }

        public string Name
        {
            get;
            set;
        }

        public DateTime Birthday
        {
            get;
            set;
        }

        public string Adress
        {
            get;
            set;
        }        

    }
}

次に先ほどのクラスのオブジェクトをバインドさせたxamlの例です。

<Window x:Class="_0721Study.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:_0721Study"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:User x:Key="oUser"
                       Name="山田 太郎"
                       Birthday="1990/07/21"/>
    </Window.Resources>
    <WrapPanel Orientation="Horizontal">
        <Label Content="名前:"  VerticalAlignment="Center" ></Label>
        <TextBlock Text="{Binding Source={StaticResource oUser}, Path=Name}" VerticalAlignment="Center"></TextBlock>
        <Label Content="誕生日:"  VerticalAlignment="Center" ></Label>
        <TextBlock Text="{Binding Source={StaticResource oUser}, Path=Birthday}" VerticalAlignment="Center"></TextBlock>
    </WrapPanel>
</Window>

実行結果

f:id:Gappory:20170721215128p:plain

各コントロールのSource属性にStaticResourceを使ってユーザのオブジェクトを指定して、Path属性にはユーザクラスのもつプロパティを指定しています。

DataContextの使用

DataContext属性を使うことで、親要素にオブジェクトをバインドすることで子要素のバインドを一括してできるようになります。

文章で書くといまいちわかりにくくなってしまいましたが、先ほどの例をDataContextで書くと以下の通りです。

<Window x:Class="_0721Study.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:_0721Study"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:User x:Key="oUser"
                       Name="山田 太郎"
                       Birthday="1990/07/21"/>
    </Window.Resources>
    <WrapPanel Orientation="Horizontal" DataContext="{StaticResource oUser}">
        <Label Content="名前:"  VerticalAlignment="Center" ></Label>
        <TextBlock Text="{Binding Path=Name}" VerticalAlignment="Center"></TextBlock>
        <Label Content="誕生日:"  VerticalAlignment="Center" ></Label>
        <TextBlock Text="{Binding Path=Birthday}" VerticalAlignment="Center"></TextBlock>
    </WrapPanel>
</Window>

WPFでのMVVMを理解するためにも、バインディングの機能は必須になるので、しっかり使いこなせるように復習していきたいです。

【お勉強記録】C#文法学び直し。イベント

イベント

Visual Studioによって、特に考えることなく、イベント機能を使っていましたが、 イベントはあらかじめ、メソッドの参照オブジェクトを保有しておくことで、機能を実現しているようです。

イベントは発生を監視するイベントループと、イベント発生した時に実際に処理されるイベントハンドラで成り立っています。

delegateで実現できるイベントですが、C#ではさらにイベントに特化したeventキーワードが用意されています。

eventで宣言されたデリゲートは、同じクラスからのみ呼び出しはできないが、外からデリゲートにメソッドを追加できるという特徴を持っています。

using System;

namespace test
{
    class Counter
    {
        public event EventHandler ThresholdReached;

        protected virtual void OnThresholdReached(EventArgs e)
        {
            EventHandler handler = ThresholdReached;
            if (handler != null)
            {
                handler(this, e);
            }
        }
        public void Start()
        {
            System.Threading.Thread.Sleep(5000);
            if (ThresholdReached != null)
            {
                //"ThresholdReached"イベントの発生
                ThresholdReached(this, EventArgs.Empty);
            }
        }

        
    }
    class Program
    {


        static void Main(string[] args)
        {
            Counter c = new Counter();
            c.ThresholdReached += c_ThresholdReached;
            c.Start();
            Console.ReadLine();
        }
        static void c_ThresholdReached(object sender, EventArgs e)
        {
            Console.WriteLine("5秒経った後に実行");
        }

    }
}

イベントって、observerパターンに近い感じがしますね。

デザインパターンとかもしっかり勉強して、自分の中に蓄積させていきたいですねー