3

i ont le scénario suivant:Héritage de contrôle personnalisé Silverlight. Réutiliser le modèle?

[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é dans toute l'application, et contiendra un comportement et une disposition plus complexes.

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 avez pas besoin de copier/coller le modèle, un Nous avons l'avantage de garder les deux à jour avec les mêmes changements.

Comment puis-je réutiliser le ValueBoxWithLabelTemplate et remplacer uniquement la propriété content en conservant le reste du modèle?

Répondre

1

C'est une approche intrigante. 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 l'affectation d'une instance concrète d'un contrôle, ce que vous faites dans ce cas avec un TextBox. Vous ne pouvez pas utiliser TemplateBinding dans le TextBox car il ne fait pas partie d'un ControlTemplate.

Même sans le problème TemplateBinding, vous ne pourrez en aucun cas créer un contrôle, puisque vous ne pouvez pas "réutiliser" la même instance d'un TextBox en plusieurs endroits. C'est pourquoi nous avons des modèles en première place.

modèles tout le chemin

Résoudre la question de templating ne devrait pas être difficile. Le truc le plus difficile serait de trouver un moyen de lier le contrôle interne du contenu des contrôles spécialisés aux propriétés de la classe spécialisée. C'est difficile à faire quand vous ne pouvez pas utiliser TemplateBinding.

D'abord, je vais décrire les changements que vous au moins besoin de faire afin d'obtenir les contrôles 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> 

Ce que je pense (sans le tester) rendra.

La liaison Edition

Cependant, comme vous pouvez voir la liaison sur la propriété Text est manquante.Maintenant, il y a quelques choses que je peux penser qui pourraient vous aider à résoudre ce problème de liaison, mais ils impliquent soit abusant du DataContext ou créant une sous-classe de ContentPresenter pour aider les propriétés de passage du contrôle externe au contrôle interne. Les deux sont vraiment laids.

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.

+0

Merci pour vos commentaires. Je n'aurai probablement pas le temps ce week-end, mais je vais l'essayer le lundi et rendre compte :-) –

+0

Salut encore Anthony. Je me suis mis à essayer votre solution, mais pas de chance. Le problème est que je ne peux pas accéder aux "parties" dans le modèle de contrôle, ainsi la ligne suivante de dessus ne fonctionnera pas: ((DoubleClickButton) GetTemplateChild (GoToEditStateButtonPart)) DoubleClick + = (sender, args) = > IsInEditMode = true; Des pensées? –

+0

Vous avez beaucoup de bons conseils sur la question. En raison de la pression du temps sur notre projet actuel. Je n'ai pas eu le temps de creuser plus profond. Je pourrais poster plus plus tard. Merci pour votre contribution. –

Questions connexes