2017-02-13 7 views
0

Ich habe ein ItemsControl verwendet View von Produkten wie diese angezeigt werden:laden und erstellen Instanz von Datenvorlage

<ItemsControl ItemsSource="{Binding Items}"> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <ContentControl Content="{Binding View}" /> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

Im Folgenden finden Sie kurze MCVE Sie eine Idee zu geben:

public class Item 
{ 
    public string Text { get; set; } 
    public object View { get; set; } 
    ... // more properties used in bindings 
} 

public partial class MainWindow : Window 
{ 
    public ObservableCollection<Item> Items { get; } = new ObservableCollection<Item>(); 

    public MainWindow() 
    { 
     InitializeComponent(); 
     // 1 
     { 
      var control = new TextBlock(); 
      var item = new Item { Text = "1", View = control }; 
      BindingOperations.SetBinding(control, TextBlock.TextProperty, new Binding(nameof(Item.Text)) { Source = item }); 
      Items.Add(item); 
     } 
     // 2 
     { 
      var control = new CheckBox(); 
      var item = new Item { Text = "2", View = control }; 
      BindingOperations.SetBinding(control, CheckBox.ContentProperty, new Binding(nameof(Item.Text)) { Source = item }); 
      Items.Add(item); 
     } 
     // ... and so on 
     DataContext = this; 
    } 
} 

Wie Sie können sehen Sie jedes Element hat vor-erstellt View (leider kann das nicht/sollte nicht geändert werden), die alles sein kann, enthält Bindung, etc.


Meine Frage: Wie verschiebe ich die Erstellung von View in XAML (als Datenvorlagen)?

Pseudoxaml:

<SomeContainer.Resources> 
    <DataTemplate x:Key="type1"> 
     <TextBlock Text="{Binding Text}" /> 
    </DataTemplate> 
    <DataTemplate x:Key="type2"> 
     <CheckBox Content="{Binding Text}" /> 
    </DataTemplate> 
</SomeContainer.Resources> 
<ItemsControl ... /> <!-- same definition as early? --> 

Pseudo-Code

Items.Add(new Item { Text = "1", View = LoadTemplate("type1") }); 
Items.Add(new Item { Text = "2", View = LoadTemplate("type2") }); 

object LoadTemplate(string key) 
{ 
    var resource = FindResource(key); 
    ... // what next? 
} 

Antwort

1

wenn Sie absolut haben UIElements im Hinblick Modell verwenden (anstelle von Vorlagen), und zur gleichen Zeit, sie in xAML deklarieren möchte, dann

  • nicht Datatemplate
  • Verwendung x:Shared="False" auf UIElement
<Window.Resources> 
    <TextBlock x:Key="type1" x:Shared="False" Text="{Binding Text}"/> 
    <CheckBox x:Key="type2" x:Shared="False" Content="{Binding Text}"/> 
</Window.Resources> 

jedes Mal, wenn Sie eine Ressource anfordern, erhalten Sie eine neue Kopie

Loadtemplate-Methode wird verwenden, reduziert

Findresource
object LoadTemplate(string key) 
{ 
    return FindResource(key); 
} 
+0

Ich wusste, dass ich etwas Einfaches vermisse, danke. – Sinatr

1

Anstelle ein UI-Steuerelement wie ein TextBlock oder ein CheckBox in dem View-Modell erstellen Sie ein CLR-Objekt erstellen sollten:

public class MyTextClass 
{ 
    public string Text { get; set; } 
} 

... 

var view = new MyTextClass(); 
var item = new Item { Text = "1", View = control }; 

Sie könnten dann eineverwendenin der Ansicht mit einer Steuer eine Instanz des CLR-Objekt zu verknüpfen:

<DataTemplate DataType="local:MyTextClass"> 
    <TextBlock Text="{Binding Text}" /> 
</DataTemplate> 

Wenn Sie die DataType Eigenschaft eines DataTemplate gesetzt, ohne dass eine x:Key Angabe, wird die DataTemplate automatisch auf Datenobjekte dieser Art angewendet: https://msdn.microsoft.com/en-us/library/system.windows.datatemplate.datatype(v=vs.110).aspx

+0

Ich kenne den Stand ard Art der Verwendung von Datenvorlagen und während es nicht auf meinen Fall anwendbar ist, kann die Antwort für zukünftige Leser nützlich sein, danke. Aus Gründen wird "Ansicht" modifiziert, bevor es an den visuellen Baum angehängt wird (z. B. in einen anderen Container gelegt), und die verzögerte Natur der Datenvorlage macht es schwierig (unmöglich?), Dies zu erreichen. – Sinatr

Verwandte Themen