Silverlight Custom Control Vererbung. Die Vorlage wiederverwenden?
-
20-09-2019 - |
Frage
Ich habe das folgende Szenario:
[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 ist ein Bedienfeld für jede Eingabebox. Es ist jetzt einfach, wird aber während der gesamten Anwendung wiederverwendet und enthält komplexere Verhaltensweisen und Layout.
Textbox als Eingabe ist der gebrauchte Muss, daher mache ich diese Steuerung:
public class TextBoxWithLabel : ValueBoxWithLabel
{
#region Text Dependency Property ...
public TextBoxWithLabel()
{
DefaultStyleKey = typeof (TextBoxWithLabel);
}
}
Ich habe dann den aktuellen generischen.xaml, der nicht funktioniert, aber es gibt eine Vorstellung davon, was ich will:
<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>
Da ein ValueBoxWitHhlabel am meisten mit einem Textfeld verwendet wird, möchte ich dafür ein Steuerelement erstellen, das dieselbe Vorlage wiederverwendet Änderungen.
Wie kann ich die ValueBoxWitHlabeltemplate wiederverwenden und nur die Inhaltseigenschaft überschreiben, die den Rest der Vorlage behält?
Lösung
Es ist ein faszinierender Ansatz. Ich habe es nicht selbst ausprobiert, aber es sieht so aus, als könnte der Ansatz funktionieren.
Das Problem, das Sie derzeit haben, ist, dass Sie versuchen, die zu verwenden Content
Eigentum des ContentPresenter
. Dies erfordert jedoch, dass eine konkrete Instanz einer Kontrolle zugewiesen wird, die in diesem Fall mit a TextBox
. Sie können nicht verwenden TemplateBinding
in dem TextBox
Weil es nicht Teil von a ist ControlTemplate
.
Auch ohne die TemplateBinding
Problem Sie könnten sowieso nur eine Kontrolle damit erstellen, da Sie die gleiche Instanz von a nicht "wiederverwenden" können TextBox
an mehr als einem Ort. Deshalb haben wir an erster Stelle Vorlagen.
Vorlagen den ganzen Weg
Das Lösen des Vorlagenproblems sollte nicht so schwer sein. Das wirklich Trickend wäre, einen Weg zu finden, um die innere Inhaltskontrolle spezialisierter Kontrollen an Eigenschaften einer speziellen Klasse zu binden. Dies ist schwierig, wenn Sie nicht verwenden können TemplateBinding
.
Zuerst werde ich nur die Änderungen skizzieren, die Sie zumindest vornehmen müssen, um die Steuerung zu erhalten:-
<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>
Das TextBoxWithLabel
wird:-
<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>
Dies denke ich (ohne es zu testen).
Das Bindungsproblem
Wie Sie jedoch die Bindung an der sehen können Text
Eigentum fehlt. Jetzt gibt es ein paar Dinge, die ich mir vorstellen kann, die Ihnen helfen könnte, dieses Bindungsproblem zu lösen, aber sie beinhalten beide, die das Missbrauch zu haben DataContext
oder eine Unterklasse erstellen von ContentPresenter
Um durch die Überwachung von Eigenschaften von der äußeren Kontrolle bis zum inneren zu helfen. Beide sind wirklich hässlich.
Fazit
Für eine so einfache Basisvorlage sind Sie wahrscheinlich besser dran, die Vorlage zu duplizieren, als alle Reifen zu springen, die erforderlich sind, um eine Art Wiederverwendung zu erreichen.