2016-04-11 7 views
1

Ich habe ein Itemscontrol mit einem Canvas als ItemsPanelTemplate und mehrere DataTemplates wie folgt aus:Itemscontrol mit mehreren Datatemplates

<ItemsControl ItemsSource="{Binding Path=DisplayObjects}"> 

     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <Canvas /> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 

     <ItemsControl.Resources> 
      <DataTemplate DataType="{x:Type viewModels:Object1ViewModel}"> 
       <views:Object1UIElement/> 
      </DataTemplate> 

      <DataTemplate DataType="{x:Type viewModels:Object2ViewModel}"> 
       <viewModels:Object2UIElement/> 
      </DataTemplate> 
     </ItemsControl.Resources > 

     <ItemsControl.ItemContainerStyle> 
      <Style TargetType="ContentPresenter"> 
       <Setter Property="Canvas.Left" Value="{Binding Path=X"/> 
       <Setter Property="Canvas.Top" Value="{Binding Path=Y"/> 
       <!-- Serveral more properties that are either attached to the Canvas or UIElement --> 
      </Style> 
     </ItemsControl.ItemContainerStyle> 

    </ItemsControl> 

Die beiden Viewmodels Lage (X, Y) auf die Leinwand links und Topeigenschaft gebunden ist. Das Problem besteht darin, dass ich die viewModels-Eigenschaften auf verschiedene Arten an Canvas binden möchte. Beispiel: Object1ViewModel Verwenden Sie einen MultiBinding-Konverter, der einen Wert abhängig von Faktoren wie der Größe von ItemControl zurückgibt, wobei Object2ViewModel direkt an die Canvas Left/Top-Eigenschaften wie oben gezeigt gebunden werden soll.

Ich habe versucht, die Bindung direkt in der DataTemplate zu setzen, damit ich unterschiedliche Bindungsstile für verschiedene DataTemplates haben kann, aber das funktioniert nicht .. Die Objekte werden Canvas nicht finden, wie sie in einem ContentPresenter erstellt werden.

+2

Klingt, als ob Sie zwei verschiedene ItemContainerStyles benötigen. Sie können die ItemControl-Eigenschaft ['ItemContainerStyleSelector'] (https://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.itemcontainerstyleselector (v = vs.110) .aspx) auf eine entsprechende Eigenschaft setzen Stilauswahl. – Clemens

+1

@Clemens Danke, ich habe es mit deinem Kommentar herausgefunden und meine Implementierung gepostet. – Daltons

Antwort

2

Also habe ich es mit dem Kommentar von Clemens herausgefunden. Als er erwähnte, brauchte ich ein ItemContainerStyleSelector so machte ich die Klasse, die mir den entsprechenden Stil geben würde:

public class MyItemContainerStyleSelector : StyleSelector 
{ 
    public override Style SelectStyle(object item, DependencyObject container) 
    { 
     var element = container as FrameworkElement; // this will be a ContentPresenter 
     if (element == null) return null; 
     var viewModel = element.DataContext; 
     if (viewModel is Object1ViewModel) 
     { 
      return element.FindResource("Object1Style") as Style; 
     } 
     if (viewModel is Object2ViewModel) 
     { 
      return element.FindResource("Object2Style") as Style; 
     } 
     return null; 
    } 
} 

in XAML würde ich die Stile in den Ressourcen definieren und ItemContainerStyleSelector zu meinem neuen Stil Wähler:

<UserControl.Resources> 
    <utilities:MyItemContainerStyleSelector x:Key="MyStyleSelector"/> 

    <Style x:Key="Object1Style" TargetType="ContentPresenter"> 
     ... 
    </Style> 

    <Style x:Key="Object2Style" TargetType="ContentPresenter"> 
     ... 
    </Style> 
</UserControl.Resources> 

<ItemsControl 
    ... 
    ItemContainerStyleSelector="{StaticResource MyStyleSelector}" > 
</ItemsControl> 

Dabei darf die Eigenschaft ItemContainerStyle nicht gesetzt sein oder der Style Selector wird ignoriert.

0

Klingt, als ob Sie eine DataTemplateSelector brauchen?

public class MyWonderfulTemplateSelector : DataTemplateSelector 
{ 
    public override DataTemplate 
     SelectTemplate(object item, DependencyObject container) 
    { 
     FrameworkElement element = container as FrameworkElement; 

     if (element != Object1ViewModel) 
     { 
      return element.FindResource("DataTemplate1") as DataTemplate; 
     } else if (element != Object2ViewModel) { 
      return element.FindResource("DataTemplate2") as DataTemplate; 
     } 

     return null; 
    } 
} 

Oder etwas in diese Richtung.

Verwandte Themen