Question

J'ai le scénario suivant:

[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 est essentiel un panneau pour tout inputbox. Il est simple maintenant, mais sera réutilisée dans l'application, et contiendra behavoir plus complexe et la mise en page.

TextBox comme entrée est le moût utilisé, donc je fais ce contrôle:

public class TextBoxWithLabel : ValueBoxWithLabel
{
    #region Text Dependency Property ...

    public TextBoxWithLabel()
    {
        DefaultStyleKey = typeof (TextBoxWithLabel);
    }
}

J'ai alors le generic.xaml actuel, qui ne marche pas le travail, mais il donne en idée de ce que je veux:

<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>

Depuis un ValueBoxWithLabel est le plus utilisé avec une zone de texte je veux faire un contrôle pour ce qui réutilise le même modèle, donc je ne besoin de copier / coller le modèle, et ont la headace de maintenir à la fois la mise à jour avec les mêmes modifications.

Comment puis-je réutiliser le ValueBoxWithLabelTemplate et seulement remplacer la propriété du contenu en gardant le reste du modèle?

Était-ce utile?

La solution

L'une approche intéressante. Je ne l'ai pas essayé moi-même, mais il semble que l'approche pourrait fonctionner.

Le problème que vous avez actuellement est que vous essayez d'utiliser la propriété Content du ContentPresenter. Cependant cela nécessite un cas concret d'un contrôle est affecté dans ce cas que vous faites avec un TextBox. Vous ne pouvez pas utiliser TemplateBinding dans le TextBox parce qu'il ne fait pas partie d'un ControlTemplate.

Même sans la question de TemplateBinding vous ne pourrez en créer un contrôle avec elle de toute façon, puisque vous ne pouvez pas « réutiliser » la même instance d'un TextBox dans plus d'un endroit. Voilà pourquoi nous avons des modèles en premier lieu.

Modèles tout le chemin

Résoudre la question de templating ne devrait pas être difficile. La chose vraiment duper serait de trouver un moyen de lier le contrôle du contenu interne des contrôles spécialisés aux propriétés de la classe spécialisée. Il est difficile de sorte que lorsque vous ne pouvez pas utiliser TemplateBinding.

D'abord, je vais décrire les changements que vous au moins besoin de faire pour obtenir les commandes de rendu: -

<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>

Le TextBoxWithLabel devient: -

<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>

Je pense (sans le tester) sera rendu.

La question de reliure

Cependant, comme vous pouvez voir la liaison sur la propriété Text manque. Maintenant, il y a deux ou trois choses que je peux penser à qui pourrait vous aider à résoudre ce problème contraignant mais ils impliquent abuser soit la DataContext ou la création d'une sous-classe de ContentPresenter pour aider à passer par-propriétés de contrôle externe à l'intérieure. Les deux sont merder.

Conclusion

Pour un modèle simple de base, vous êtes probablement mieux dupliquer le modèle que de sauter à travers tous les cerceaux nécessaires pour acheive une sorte de réutilisation.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top