2016-09-05 2 views
0

Ich möchte ein Raster mit ähnlichen Steuerelementen erstellen, das eine Vorlage und ein MVVM-Muster verwendet. Hier ist eine einfache Beschreibung des Problems, das ich habe. ich zum ersten Mal eine Klasse Element definieren, um für jedes Element des Grid instanziert werden:Separate Bindung an mehrere Instanzen eines Vorlagensteuerelements

public class Element : INotifyPropertyChanged 
{ 
    private string _dText = "Default"; 
    public string dText { get { return _dText; } set { _dText = value; NotifyPropertyChanged("dText"); } } 

    internal Element(string aText) { dText = aText; } 

    public event PropertyChangedEventHandler PropertyChanged; 
    private void NotifyPropertyChanged(String info) 
    { 
     var handler = PropertyChanged; 
     if (handler != null) 
      handler(this, new PropertyChangedEventArgs(info)); 
    } 
} 

Dann instanziieren ich einige Elemente innerhalb einer Ansichtsmodell-Klasse, die die Datacontext-Seite ist wie folgt: Jetzt

public class MinVM 
{ 
    private Element _element0 = new Element("Element0 initialization text 0"); 
    public Element element0 { get { return _element0; } set { _element0 = value; } } 
    private Element _element1 = new Element("Element1 initialization text 1"); 
    public Element element1 { get { return _element1; } set { _element1 = value; } } 
} 

in den XAML Page.PageResources erstelle ich eine Control entworfen mir etwas schön zentriert Text zu erhalten, wie folgt:

<ControlTemplate x:Name="cTemplate" x:Key="CTemplate" TargetType="ContentControl"> 
     <Grid x:Name="ctGrid" Background="Orange" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> 
      <TextBox x:Name ="dtBox" Background="Orange" BorderThickness="0" 
       VerticalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap" 
       Text="{Binding dText, FallbackValue=Default control template text}"> 
      </TextBox> 
     </Grid> 
    </ControlTemplate> 

schließlich in der Seite Inhalt selbst, instanziiert ich das Gitter und Elemente in sich, wie folgt:

<ContentControl x:Name="element0" Grid.Row="0" Template="{StaticResource CTemplate}" Content="{Binding Path=element0}"></ContentControl> 
    <ContentControl x:Name="element1" Grid.Row="1" Template="{StaticResource CTemplate}" Content="{Binding Path=element1}"></ContentControl> 

Das alles fein macht, wie man erwarten würde, aber die Bindung nicht funktioniert, dh ich kann nicht den Standardtext ändern, weil WPF nach einem Feld dText in MinVM sucht, nicht innerhalb des Elements. Dies liegt daran, dass ControlTemplate Content = "{Binding Path = element0}" ignoriert

Der offensichtliche Weg zu versuchen, es zu beheben, ist eine DataTemplate anstelle einer ControlTemplate zu verwenden. Ich habe das gemacht - eine DataTemplate mit genau den gleichen Interna wie das obige ControlTemplate erstellt, mit Key = "DTemplate". Ich habe dann die XAML Instanziierung ändern

<ContentControl x:Name="element0" Grid.Row="0" ContentTemplate="{StaticResource DTemplate}" Content="{Binding Path=element0}"></ContentControl> 
    <ContentControl x:Name="element1" Grid.Row="1" ContentTemplate="{StaticResource DTemplate}" Content="{Binding Path=element1}"></ContentControl> 

Nun ist die Bindung ordnungsgemäß funktioniert, wie man erwarten würde - ich kann glücklich die Kontrolle Text ändern. Aber das Rendering funktioniert nicht mehr richtig (der Text ist nicht mehr zentriert im Grid-Element, und das Orange füllt nicht länger die Grid-Zelle), weil ich die ControlTemplate verloren habe

Also kann ich es entweder richtig rendern lassen, oder binden, aber nicht beides.

Antwort

1

Wenn ich verstehe, was Sie richtig, dann müssen die folgenden XAML für mich funktioniert (man kann nur den Style extrahieren):

<Window x:Class="WpfScratch.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:WpfScratch" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
     <DataTemplate x:Key="ContentTemplate"> 
      <TextBox TextAlignment="Center" Text="The obvious way to try and fix it is to use a DataTemplate instead of a ControlTemplate. I've done that - created a DataTemplate with exactly the same internals as the above ControlTemplate, with Key=DTemplate. I then change the instantiation XAML to" TextWrapping="Wrap"/> 
     </DataTemplate> 
     <Style x:Key="ContentControlStyle1" TargetType="{x:Type ContentControl}"> 
      <Setter Property="HorizontalAlignment" Value="Stretch"/> 
      <Setter Property="VerticalAlignment" Value="Stretch"/> 
      <Setter Property="HorizontalContentAlignment" Value="Center"/> 
      <Setter Property="VerticalContentAlignment" Value="Center"/> 
      <Setter Property="ContentTemplate" Value="{StaticResource ContentTemplate}"/> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="{x:Type ContentControl}"> 
         <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </Window.Resources> 
    <Grid> 
     <ContentControl Margin="4" Style="{DynamicResource ContentControlStyle1}"/> 
    </Grid> 
</Window> 
+0

Ich glaube, ich verstehe mehr von dem, was Sie versuchen, jetzt zu tun, und denken Sie suchen nach einem Stil und nicht nach einer Vorlage. Unabhängig davon, ob Sie ein DataTemplate oder ein ControlTemplate verwenden, müssen die Eigenschaften für die horizontale und vertikale Ausrichtung des ContentControls so festgelegt werden, dass sich der eigentliche Inhalt im containing-Element zentriert. Wenn Sie diese Art von Verhalten einmal definieren und überall verwenden möchten, sollten Sie einen Style mit Settors für die Ausrichtungseigenschaften verwenden und dann den Style auf das ContentControl anwenden. – ibebbs

+0

Danke; das funktioniert perfekt. Ich habe das DataTemplate beibehalten und es um die zusätzlichen benötigten Elemente erweitert und das ControlTemplate durch den Style ersetzt. Die TemplateBinding-Eigenschaft war das andere Stück, das ich brauchte. Möchten Sie Ihren Beitrag bearbeiten, um die 1., 2., 3. Punkte zu entfernen, und ich werde als Antwort markieren. – jbhelicon

+0

Fertig. Froh, dass es geholfen hat. – ibebbs