私は最初の WPF カスタム コントロールを開発していますが、いくつかの問題に直面しています。現在使用しているコードの簡略化されたバージョンは次のとおりです。
using System.Windows;
using System.Windows.Controls;
namespace MyControls
{
[TemplatePart(Name = "PART_Button", Type = typeof (Button))]
public class MyControl : Control
{
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof (object), typeof (MyControl), new PropertyMetadata(null, OnLabelPropertyChanged));
private Button _buttonElement;
public object Content
{
get { return this.GetValue(LabelProperty); }
set { this.SetValue(ContentProperty, value); }
}
static MyControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof (MyControl), new FrameworkPropertyMetadata(typeof (MyControl)));
}
private static void OnContentPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
MyControl myControl = sender as MyControl;
if (myControl != null && myControl._buttonElement != null)
myControl._buttonElement.Content = e.NewValue;
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
this._buttonElement = this.Template.FindName("PART_Button", this) as Button;
}
}
}
これは私のカスタム コントロールのテンプレートです。
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyControls">
<Style TargetType="{x:Type local:MyControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyControl}">
<Button x:Name="PART_Button" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
次に、それを Grid 内に配置し、その Content プロパティを設定しようとします。
<Grid x:Name="layoutRoot">
<controls:MyControl x:Name="myControl" />
</Grid>
コードビハインドは次のとおりです。
using System.Windows;
namespace MyControls
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
this.myControl.Content = "test";
}
}
}
何らかの理由で、OnContentPropertyChanged コールバックが OnApplyTemplate の前に呼び出されるため、myControl._buttonElement の割り当てが遅すぎて、コンテンツを設定しようとしても null のままです。なぜこれが起こっているのですか?どうすればこの動作を変更できますか?
また、完全な設計時のサポートを提供する必要がありますが、Grid コントロールが ColumnDefinitions で行うように、カスタム コントロールが追加のマークアップを受け入れるようにする方法が見つかりません。
<Grid x:Name="layoutRoot">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
</Grid>
どんな助けでも大歓迎です!
アップデート
コントロール プロパティが設定された後に OnApplyTemplate メソッドが呼び出される理由を説明するドキュメントを見つけました。
http://msdn.microsoft.com/en-us/library/dd351483%28v=vs.95%29.aspx
問題は、(XAML またはプログラムで) 設定されたプロパティと、コントロールが初期化されていないときに呼び出されるメソッドを追跡して、OnApplyTemplate メソッドが呼び出されたときにそれらを設定/呼び出すことができるようにするにはどうすればよいかということです。コードを複製せずに、コントロールの初期化の前後で同じコールバック/メソッドを機能させるにはどうすればよいでしょうか?