Silverlightカスタムコントロール継承。テンプレートを再利用しますか?
-
20-09-2019 - |
質問
次のシナリオがあります。
[TemplatePart(Name = GoToEditModeButtonPart, Type = typeof(DoubleClickButton))]
public class ValueBoxWithLabel : ContentControl
{
public const string GoToEditModeButtonPart = "GoToEditModeButtonPart";
#region LabelText Dependency Property ...
#region IsInEditMode Dependency Property ...
public event EventHandler<ModeChangedEventArgs> ModeChanged;
public ValueBoxWithLabel()
{
DefaultStyleKey = typeof (ValueBoxWithLabel);
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
//IsInEditMode invokes ModeChanged in the dependency property
((DoubleClickButton) GetTemplateChild(GoToEditModeButtonPart)).DoubleClick += (sender, args) => IsInEditMode = true;
}
private void InvokeModeChanged(ModeChangedEventArgs e)
{
EventHandler<ModeChangedEventArgs> mode = ModeChanged;
if (mode != null)
mode(this, e);
}
}
ValueBoxは、任意の入力ボックスに不可欠です。現在は簡単ですが、アプリケーション全体で再利用され、より複雑な動作とレイアウトが含まれます。
入力としてのテキストボックスは使用する必要があるため、このコントロールを作成します。
public class TextBoxWithLabel : ValueBoxWithLabel
{
#region Text Dependency Property ...
public TextBoxWithLabel()
{
DefaultStyleKey = typeof (TextBoxWithLabel);
}
}
次に、現在のgeneric.xamlを持っていますが、それは機能しませんが、それは私が望むもののアイデアを与えます:
<ResourceDictionary>
<ControlTemplate x:Key="ValueBoxWithLabelTemplate">
<StackPanel Style="{StaticResource ValueBoxWithLabelPanelStyle}">
<TextBlock Style="{StaticResource LabelStyle}" Text="{TemplateBinding LabelText}" />
<Grid>
<ContentPresenter Content="{TemplateBinding Content}" />
<local:DoubleClickButton Background="Black" x:Name="GoToEditModeButtonPart"></local:DoubleClickButton>
</Grid>
</StackPanel>
</ControlTemplate>
<Style TargetType="local:ValueBoxWithLabel">
<Setter Property="Template" Value="{StaticResource ValueBoxWithLabelTemplate}" />
</Style>
<Style TargetType="local:TextBoxWithLabel">
<Setter Property="Template" Value="{StaticResource ValueBoxWithLabelTemplate}" />
<Setter Property="Content">
<Setter.Value>
<TextBox Style="{StaticResource ValueBoxStyle}" Text="{TemplateBinding Text}" />
</Setter.Value>
</Setter>
</Style>
ValueBoxWithLabelはテキストボックスで最も使用されているため、同じテンプレートを再利用するためにコントロールしたいので、テンプレートをコピー/貼り付けて、同じものを同じもので最新の状態に保つ必要はありません。変更。
ValueBoxWithLabelTemplateを再利用して、テンプレートの残りの部分を保持しているコンテンツプロパティをオーバーライドするにはどうすればよいですか?
解決
その興味深いアプローチ。私はそれを自分で試したことはありませんが、アプローチが機能するように見えます。
あなたが現在持っている問題はあなたが使用しようとしていることです Content
のプロパティ ContentPresenter
. 。ただし、この場合、コントロールの具体的なインスタンスが割り当てられる必要があります。 TextBox
. 。使用できません TemplateBinding
の中に TextBox
それはの一部ではないからです ControlTemplate
.
なくても TemplateBinding
問題は、同じインスタンスを「再利用」することはできないため、とにかく1つのコントロールのみを作成できます。 TextBox
複数の場所で。そのため、1位にテンプレートがあります。
テンプレートずつ
テンプレートの問題を解決することはそれほど難しくないはずです。本当にだまされているのは、特殊なコントロールの内部コンテンツ制御を専門クラスの特性に結合する方法を見つけることです。使用できない場合、これは難しいです TemplateBinding
.
最初に、コントロールのレンダリングを取得するために、少なくとも必要な変更の概要を説明します。
<ControlTemplate x:Key="ValueBoxWithLabelTemplate">
<StackPanel Style="{StaticResource ValueBoxWithLabelPanelStyle}">
<TextBlock Style="{StaticResource LabelStyle}" Text="{TemplateBinding LabelText}" />
<Grid>
<ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" />
<local:DoubleClickButton Background="Black" x:Name="GoToEditModeButtonPart"></local:DoubleClickButton>
</Grid>
</StackPanel>
</ControlTemplate>
TextBoxWithLabel
なる: -
<Style TargetType="local:TextBoxWithLabel">
<Setter Property="Template" Value="{StaticResource ValueBoxWithLabelTemplate}" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBox Style="{StaticResource ValueBoxStyle}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
これは(テストせずに)レンダリングすると思います。
拘束力のある問題
ただし、のバインディングがわかります Text
プロパティがありません。今、私はあなたがこの拘束力のある問題を解決するのに役立つと思うことができることがいくつかありますが、それらはどちらかを虐待することを伴います DataContext
または、のサブクラスを作成します ContentPresenter
外側のコントロールから内側のプロパティへのパススループロパティを支援します。どちらも本当に醜いです。
結論
このようなシンプルなベーステンプレートの場合、ある種の再利用に必要なすべてのフープを飛び越えるよりも、テンプレートを複製する方が良いでしょう。