Domanda

ho il seguente scenario:

[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 è essenziale un pannello per qualsiasi inputbox. È semplice ora, ma verrà riutilizzata durante l'applicazione, e conterrà behavoir e la layout più complessi.

TextBox come input il mosto utilizzato, quindi faccio questo controllo:

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

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

Ho poi avuto il generic.xaml attuale, che pretende molto lavoro, ma dà a un'idea di ciò che voglio:

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

Dal momento che un ValueBoxWithLabel è più usate con una TextBox voglio fare un controllo per questo, che riutilizza lo stesso modello, in modo da non ho bisogno di copiare / incollare il modello, e hanno la headace di mantenere sia up-to-date con le stesse modifiche.

Come posso riutilizzare il ValueBoxWithLabelTemplate e sovrascrivere solo la proprietà dei contenuti mantenendo il resto del modello?

È stato utile?

Soluzione

Il suo un approccio intrigante. Non ho provato io stesso, ma sembra che l'approccio potrebbe funzionare.

Il problema si deve avere è attualmente si sta tentando di utilizzare la proprietà Content del ContentPresenter. Tuttavia che richiede un'istanza concreta di un controllo da assegnare che in questo caso si sta facendo con un TextBox. Non è possibile utilizzare TemplateBinding nel TextBox perché non è parte di un ControlTemplate.

Anche senza il problema TemplateBinding si sarebbe solo in grado di creare un controllo con lo stesso, dal momento che non può la stessa istanza di un TextBox "riutilizzo" in più di un posto. Ecco perché abbiamo modelli in primo luogo.

Modelli tutta la strada

La soluzione del problema di template, non dovrebbe essere difficile. La cosa veramente ingannando sarebbe quella di trovare un modo per associare il controllo contenuto interno di controlli specializzati per le proprietà di classe specializzata. Questo è difficile da così quando non è possibile utilizzare TemplateBinding.

Per prima cosa mi limiterò a delineare i cambiamenti si avrebbe almeno bisogno di fare al fine di ottenere i controlli di rendering: -

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

Il TextBoxWithLabel diventa: -

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

Questa penso (senza prove) renderà.

La questione Binding

Tuttavia, come si può vedere la vincolanti per la proprietà Text manca. Ora ci sono un paio di cose mi viene in mente che potrebbe aiutare a risolvere questo problema vincolante ma comportano o abusare del DataContext o la creazione di una sottoclasse di ContentPresenter per aiutare pass-through oggetti di controllo esterno per quello interno. Entrambi sono davvero brutta.

Conclusione

Per un tale modello di base semplice che si sono probabilmente meglio duplicare il modello che saltare attraverso tutti i cerchi necessari per acheive un qualche tipo di riutilizzo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top