次の方法で共有


繰り返し出現するXAML構造の再利用方法ついて

質問

2015年3月2日月曜日 6:01

.NET Framework 4.0にてWPFを使用しています。
WPFを使用するのは今回が初めてで、現在勉強中です。
開発環境はVisual Studio 2013 Professionalです。

下記のような一式のコントロールを様々なところで使いまわします。

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="5*"/>
            <ColumnDefinition Width="1*"/>
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Column="0" VerticalAlignment="Center">
            Name
        </TextBlock>
        <TextBox Grid.Column="1" TextAlignment="Right" VerticalAlignment="Center">
            Value
        </TextBox>
        <TextBlock Grid.Column="2" VerticalAlignment="Center">
            Unit
        </TextBlock>
  </Grid>

※ただし、Name, Value, Unitは配置場所によって中身が異なります。

上記のような一式のXAML構造を様々なところで効率的に使いまわすにはどのような方法が適しているのでしょうか?

ユーザーコントロールにひとまとめにして……とWindows Formのようなやり方を考えているのですが、その場合Name, Value, UnitをXAML上に記述する方法がわかりません。

XAMLのパーツを効率的使いまわす(かつ、部分的なプロパティを配置場所ごとに設定可能にする)方法がありましたらご教授お願いします。

すべての返信 (2)

2015年3月2日月曜日 6:24 ✅回答済み | 1 票

こんにちは。

UserControlが良いのか、Styleが良いのか、添付プロパティが良いのかなど
ケースバイケースですが・・・

UserControlの場合は依存関係プロパティを作成しUserControl.xamlの中でバインドするのはどうですかね。

    public partial class UserControl1 : UserControl
    {
        public UserControl1()
        {
            InitializeComponent();
        }

        public static readonly DependencyProperty HogeNameProperty =
            DependencyProperty.Register("HogeName", typeof(string), typeof(UserControl1), new UIPropertyMetadata(string.Empty));
        public static readonly DependencyProperty HogeValueProperty =
            DependencyProperty.Register("HogeValue", typeof(string), typeof(UserControl1), new UIPropertyMetadata(string.Empty));
        public static readonly DependencyProperty HogeUnitProperty =
            DependencyProperty.Register("HogeUnit", typeof(string), typeof(UserControl1), new UIPropertyMetadata(string.Empty));

        public string HogeName
        {
            get { return (string)GetValue(HogeNameProperty); }
            set { SetValue(HogeNameProperty, value); }
        }
        public string HogeValue
        {
            get { return (string)GetValue(HogeValueProperty); }
            set { SetValue(HogeValueProperty, value); }
        }
        public string HogeUnit
        {
            get { return (string)GetValue(HogeUnitProperty); }
            set { SetValue(HogeUnitProperty, value); }
        }
    }
<UserControl x:Class="WpfApplication3.UserControl1"
             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" 
             mc:Ignorable="d" 
             Name="Hoge"
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="5*"/>
            <ColumnDefinition Width="1*"/>
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Column="0" VerticalAlignment="Center" Text="{Binding ElementName=Hoge, Path=HogeName}" />
        <TextBox Grid.Column="1" TextAlignment="Right" VerticalAlignment="Center" Text="{Binding ElementName=Hoge, Path=HogeValue}" />
        <TextBlock Grid.Column="2" VerticalAlignment="Center" Text="{Binding ElementName=Hoge, Path=HogeUnit}" />
    </Grid>
</UserControl>
<Window x:Class="WpfApplication3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication3"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel Orientation="Vertical">
        <local:UserControl1 HogeName="Name1" HogeValue="Val1" HogeUnit="UnitA" />
        <local:UserControl1 HogeName="Name2" HogeValue="Val2" HogeUnit="UnitB" />
    </StackPanel>
</Window>

2015年3月2日月曜日 6:29 ✅回答済み | 1 票

詳しい仕様がわかりませんが、一般的にはUserControlが良いように思います。具体的には、UserControlにそれぞれのTextBlockにバインドするプロパティを設けて、設定する際にはそのプロパティに対してそれぞれの値を設定すれば良いでしょう。実際の実装はMVVMパターンを採用しているかどうかによっても変わりますが、基本的に行うことは同じです。
また、以下のスレッドも参考にしてみて下さい。

(参考)
共通の要素を集約したい 
https://social.msdn.microsoft.com/Forums/ja-JP/58eae198-e7fe-441c-809b-a6fdfcd9d3b1?forum=wpfja

★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/