カスタムコントロールのXAMLとコード
プロジェクトにカスタムコントロールを追加すると、Themes フォルダが作られ generic.xaml が生成されます。
このファイルは、プロジェクトに1つ生成されます。
これは、複数のコントロールが1つのXAMLに記述されることになり、流用しようとすると切り出す必要が生じることになると考え避けていました。
コントロール
コントロールの概念を少し整理しておきます。
デザイナでWindowをデザインする際の、操作する単位を、普通、コントロールと呼んでいると思います。
WPFやSilvrerlightは、このコントロールをデザインすることができるようになっています。
Windowに配置できるパーツの分類は、以下のように見えます。
UIElement |
|
|
|
|
Grid |
|
|
|
|
: |
|
|
|
|
|
|
|
- |
Control |
Button |
|
|
|
|
TextBox |
|
|
|
|
ComboBox |
|
|
|
|
: |
|
|
|
|
|
|
|
- |
Shape |
Line |
|
|
|
|
Ellipse |
|
|
|
|
: |
|
|
|
|
|
|
|
- |
TextBlock |
|
|
|
|
Border |
|
|
|
|
: |
|
パーツに共通するのは、FrameworkElement のようです。
Control は、FrameworkElemet を集めて作られているもので、Windowに配置できるものの1つのようです。
カスタムコントロール
カスタムコントロールをプロジェクトに追加してみます。
generic.xaml には、Style が作られます。
- <Style TargetType="{x:Type local:CustomControl1}">
- <Setter Property="Template">
- <Setter.Value>
- <ControlTemplate TargetType="{x:Type local:CustomControl1}">
- <Border Background="{TemplateBinding Background}"
- BorderBrush="{TemplateBinding BorderBrush}"
- BorderThickness="{TemplateBinding BorderThickness}">
- </Border>
- </ControlTemplate>
- </Setter.Value>
- </Setter>
- </Style>
CustomControl1.csには、以下のCustomControl1クラスが作られます。
- public class CustomControl1 : Control
- {
- static CustomControl1()
- {
- DefaultStyleKeyProperty.OverrideMetadata(
- typeof(CustomControl1),
- new FrameworkPropertyMetadata(typeof(CustomControl1)));
- }
- }
Control のTemplate を定義すれば、ButtonでもTextBlockでも任意のものが作れると言う仕組みです。
XAML記述とコードの関係
CustomControl1クラスに、property1 と言うプロパティを追加して、XAML記述で値を設定してみます。
generic.xaml には、以下のような記述を追加します。
- <Setter Property="property1">
- <Setter.Value>
- <DoubleCollection>
- 0,1,2,3
- </DoubleCollection>
- </Setter.Value>
- </Setter>
- 0,1,2,3
- </DoubleCollection>
- </Setter.Value>
- </Setter>
- 0,1,2,3
- </DoubleCollection>
- </Setter.Value>
- </Setter>
プロパティの名前は、CustomControl1クラスに、public なプロパティが宣言されていればコンパイルができます。
しかし、実行時にはエラーになります。
エラーにならないようにするには、依存関係プロパティとして宣言する必要があるようです。
このプロパティの登録や変更イベント処理はスタティックで、コンストラクト前にアクセスされるもののようです。
- public class CustomControl1 : Control
- {
- // プロパティを追加
- public DoubleCollection property1 { get; set; }
- // このプロパティを依存関係プロパティに登録
- public static readonly DependencyProperty property1Property =
- DependencyProperty.Register(
- "property1",
- typeof(DoubleCollection),
- typeof(CustomControl1),
- new PropertyMetadata(property1PropertyChanged));
- // 依存関係プロパティの変更イベント(スタティック)
- static void property1PropertyChanged(DependencyObject d,
- DependencyPropertyChangedEventArgs e)
- {
- ((CustomControl1)d).property1=
- (DoubleCollection)e.NewValue;
- }
- // スタティックなコンストラクタ
- static CustomControl1()
- {
- DefaultStyleKeyProperty.OverrideMetadata(
- typeof(CustomControl1),
- new FrameworkPropertyMetadata(typeof(CustomControl1)));
- }
- // 通常のコンストラクタ
- public CustomControl1()
- {
- // この段階では、property1はnull
- // Loadedイベント処理を登録
- Loaded += new RoutedEventHandler(CustomControl1_Loaded);
- }
- // Loadedイベント
- void CustomControl1_Loaded(object sender, RoutedEventArgs e)
- {
- Debug.WriteLine(property1);// 0 1 2 3 と表示
- }
- }
参照
問題を整理すると、
-
XAMLを分割して記述する方法
-
記述1つから複数のインスタンスを得る方法
と、言うことになります。
「XAMLとビハインドコード」
「カスタムコントロールのXAMLとコード」
「Styleとプロパティ」
「Styleとバインディング」
「DataContextとインスタンス」
「XAML記述とVisualの変換」
「1つのStyle記述から複数のインスタンス」
|