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?

War es hilfreich?

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top