BlogTechnology

【WPF】Refer Resource definition by Code behind

 

 

 

概要

 

WPFで独自クラスをインスタンス化する場合、次の二つの方法があります。

 

  1. 従来のWindowsフォームのようにコードビハインドでインスタンス化する方法
  2. XAMLでリソース定義をしてインスタンス化する方法

 

コードビハインドでインスタンス化したクラスを呼び出す場合、上記1.の方法は問題ありませんが、上記2.のXAMLでインスタンス化された独自クラスの呼び出し方はWPF特有ですのでメモしておきます。

 

 

 

環境

 

Microsoft Visual Studio 2015 + WPF + VB

 

 

 

XAMLのリソースを定義または参照する方法

 

独自クラス

 

XAMLでのリソース定義

WPFでは、XAMLでリソースを定義(クラスの場合はインスタンス化)できます。その方法は、Resoucesタグにインスタンス化したいクラスの名称とそれを参照するためのキーを登録するだけです。

[code lang=”html”]<my:対象のクラス名 x:Key=”参照するためのキー” />[/code]

 

XAMLでリソース参照

XAMLから参照する場合は、次のように参照した内容を設定したいコントロールのプロパティにバインディングさせることで可能です。
ここでは、Sourceに先ほど定義したリソース(クラス)のキーを、pathにはリソース(クラス)のプロパティを設定します。Modeには該当のコントロールのプロパティに値を設定するだけであればoneWay(単方向)を、値を設定または参照する場合はTwoWay(双方向)を指定します。

[code lang=”html”]<TextBlock Text=”{Binding Source={StaticResource リソースのキー}, Path=リソースのプロパティ, Mode=OnwWayまたはTwoWay}”/>[/code]

 

コードビハインドでリソース参照

リソースに定義済みのクラスのメソッドを呼び出すときはResoucesプロパティまたはFindResourceメソッドを使用します。Resourcesプロパティの場合は、カッコ内にリソース名を設定するとリソースの参照が可能となり、コードビハインドでクラスを呼び出すことができるようになります。

 

Resourcesプロパティを使用する場合

[code lang=”vb”]Me.Resources(“リソースのキー“).プロパティまたはメソッド[/code]

FindResourceメソッドを使用する場合

[code lang=”vb”]Me.FindResource(“リソースのキー“).プロパティまたはメソッド[/code]

 

数値や文字列(名前空間systemで定義されたクラス)

 

数値や文字列をXAMLでリソース定義および参照する場合は、Window定義における「xmlns:system=”clr-namespace:System;assembly=mscorlib”」は、コアアセンブリ(mscorlib)のSystem名前空間に対応するXML中の名前空間”system”を定義する必要があります。

 

XAMLでのリソース定義

WPFでは、XAMLでリソースを定義(クラスの場合はインスタンス化)できます。その方法は、Resoucesタグにインスタンス化したいクラスの名称とそれを参照するためのキーを登録するだけです。

[code lang=”html”]<system:数値または文字列の型のクラス※ x:Key=”参照するためのキー“>数値または文字列</system:数値または文字列の型のクラス※>[/code]

※数値または文字列の型のクラスにはInteger,Double,String等の型クラス

 

XAMLでリソース参照

XAMLから参照する場合は、次のように参照した内容を設定したいコントロールのプロパティにバインディングさせることで可能です。
ここでは、Sourceに先ほど定義したリソース(クラス)のキーを、pathにはリソース(クラス)のプロパティを設定します。Modeには該当のコントロールのプロパティに値を設定するだけであればoneWay(単方向)を、値を設定または参照する場合はTwoWay(双方向)を指定します。

[code lang=”html”]<Label Content=”{Binding Source={StaticResource リソースのキー}}” />[/code]

 

コードビハインドでリソース参照

リソースに定義済みのクラスのメソッドを呼び出すときは次のようにResoucesプロパティを使用します。Resourcesプロパティのカッコ内にリソース名を設定するとリソースの参照が可能となり、コードビハインドでクラスを呼び出すことができるようになります。

[code lang=”vb”]Me.Resources(“リソースのキー“)[/code]

 

 

 

サンプル

 

説明

 

画面に入力用の3つのテキストボックスと2つの出力用テキストボックスを配置します。

3つのテキストボックスに入力された数値の総合計と平均を2つのテキストボックスにそれぞれ出力します。

総合計と平均のテキストボックスは、それぞれ合計を取得するsumdataプロパティと平均を取得するavedataプロパティがバインディングされています。3つのいずれかのテキストボックスの内容が入力されると、再計算された値が表示されます。

Calcボタンをクリックすると、リソース(クラス)のsumdataプロパティを参照して合計を表示します。

ちなみに、コードビハインドではリソース(クラス)のメソッドやファンクションを直接呼び出すこともできます。

 

スクリーンショット

 

スクリプト

 

XAML

[code lang=”HTML”]
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:WpfAppEventTest"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<my:disp1 x:Key="disp1" />
</Window.Resources>
<Grid>
<StackPanel x:Name="Panel1" Loaded="Panel1_Loaded" Keyboard.KeyDown="TextBox_KeyDown" KeyUp="TextBox_KeyUp">
<TextBox Text="{Binding Source={StaticResource disp1}, Path=input1, Mode=TwoWay}" BorderBrush="Blue" Margin="10"/>
<TextBox Text="{Binding Source={StaticResource disp1}, Path=input2, Mode=TwoWay}" BorderBrush="Red" Margin="10" />
<TextBox Text="{Binding Source={StaticResource disp1}, Path=input3, Mode=TwoWay}" BorderBrush="Green" Margin="10"/>
<TextBlock Text="{Binding Source={StaticResource disp1}, Path=sumdata, Mode=OneWay}"/>
<TextBlock Text="{Binding Source={StaticResource disp1}, Path=avedata, Mode=OneWay}"/>
<Button Content="Calc" Click="Button_Click"/>
</StackPanel>
</Grid>

</Window>
[/code]

 

 

MainWindowクラス(コードビハインド)

[code lang=”vb”]
Class MainWindow 

    Dim clss_disp1 As disp1
    
    Private Sub TextBox_KeyDown(sender As System.Object, e As System.Windows.Input.KeyEventArgs)

    End Sub

    Private Sub TextBox_KeyUp(sender As System.Object, e As System.Windows.Input.KeyEventArgs)

    End Sub

    Private Sub Panel1_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs)

        clss_disp1 = New disp1
        Panel1.DataContext = clss_disp1
    End Sub

    Private Sub Button_Click(sender As System.Object, e As System.Windows.RoutedEventArgs)
        REM XAMLで定義したリソースを呼び出して使用する
        Me.Resources("disp1").calc()
        'WINDOWSリソースに定義したsumdataプロパティを参照して表示する
        MessageBox.Show("合計は" + Me.Resources("disp1").sumdata.ToString)
    End Sub
End Class

[/code]

 

合計値と平均値を計算する独自クラス

[code lang=”vb”]
Imports System.ComponentModel

Public Class disp1
    Implements INotifyPropertyChanged

    Private _input1 As Integer
    Private _input2 As Integer
    Private _input3 As Integer
    Private _sumdata As Integer
    Private _avedata As Integer

    Public Sub New()
        Me._input1 = 0
        Me._input2 = 0
        Me._input3 = 0
        Me._sumdata = 99
        Me._avedata = 999
    End Sub
    Public Property input1() As Integer
        Get
            Return _input1
        End Get
        Set(value As Integer)
            _input1 = value
            Me.calc()
        End Set
    End Property
    Public Property input2() As Integer
        Get
            Return _input2
        End Get
        Set(value As Integer)
            _input2 = value
            Me.calc()
        End Set
    End Property
    Public Property input3() As Integer
        Get
            Return _input3
        End Get
        Set(value As Integer)
            _input3 = value
            Me.calc()
        End Set
    End Property
    Public Property sumdata() As Integer
        Get
            Return _sumdata
        End Get
        Private Set(value As Integer)
            _sumdata = value
            OnPropertyChanged("sumdata")

        End Set
    End Property

    Public Property avedata() As Integer
        Get

            Return _avedata
        End Get
        Private Set(value As Integer)
            _avedata = value
            OnPropertyChanged("avedata")
        End Set
    End Property
    Public Sub calc()
        sumdata = input1 + input2 + input3
        avedata = sumdata / 3
    End Sub

    Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

    Protected Overridable Sub OnPropertyChanged(ByVal propertyNane As String)
        RaiseEvent PropertyChanged( _
            Me, New PropertyChangedEventArgs(propertyNane))
    End Sub

End Class

[/code]

 

 

 

まとめ

 

WPFではコードビハインドでプログラムを書かなくてもすべてXAMLで処理することができるそうです。どちらも同じように使えると、コードを書くときにどちらがいいか迷ったり、また人によって書き方がまちまちだったりするので考えものです。プロジェクトでWPFを使う場合は、そのあたりをメンバー間で話し合ってコーディング規約に反映する必要がありそうです。

 

 

 

関連記事

 

 

 

参考

 

リソースとコード

https://msdn.microsoft.com/ja-jp/library/ms752326(v=vs.110).aspx

WPFのStaticResourceとDynamicResourceの違い

WPFのStaticResourceとDynamicResourceの違い

(XAML#04)「リソースで数値や文字列を定義する」

http://blogs.itmedia.co.jp/mohno/2013/12/xaml04-170d.html

WPFサンプル:独自クラスをResourcesに指定し、StaticResourceで参照する

http://gushwell.ldblog.jp/archives/52299560.html

WPF4.5入門 その51 「リソース」

WPF 個人用メモ.1※WPF

http://diy.sinceretechnology.work/wp-admin/post.php?post=18061&action=edit

App.xamlで定義したリソースを動的に変更したい

http://d.hatena.ne.jp/hilapon/20151113/1447381150

リソースの使い方

http://ex.osaka-kyoiku.ac.jp/~fujii/WPFhp/WPF_resources.html

WPFのStaticResourceとDynamicResourceの違い – MSDN – Microsoft

https://social.msdn.microsoft.com/Forums/ja-JP/3bbcdc48-2a47-495e-9406-2555dc515c3a/wpfstaticresourcedynamicresource?forum=wpfja