2016-09-23 47 views
2

我需要用MVVM來表示兩級結構化數據。如果數據是:應該如何無直接鏈接的兩級結構化數據的WPF綁定

public class ParentEntity 
{ 
    public int UID { get; set; } 
    public string Name { get; set; } 
} 

public class ChildEntity 
{ 
    public int ParentUID { get; set; } 
    public string Name { get; set; } 
    public int Value { get; set; } 
} 

public class ParentEntity 
{ 
    public ObservableCollection<ChildEntity> ChildsEntities { get; set; } = new ObservableCollection<ChildEntity>(); 
    public string Name { get; set; } 
} 

public class ChildEntity 
{ 
    public string Name { get; set; } 
    public int Value { get; set; } 
} 

話,我會用TreeView控件創建的綁定:

<TreeView x:Name="treeView"> 
    <TreeView.Resources> 

     <!--Template for ParentEntity--> 
     <HierarchicalDataTemplate DataType="{x:Type ParentEntity}" ItemsSource="{Binding ChildsEntities}"> 
      <TextBox Text="{Binding Name}"/> 
     </HierarchicalDataTemplate> 

     <!--Template for ChildEntity--> 
     <DataTemplate DataType="{x:Type ChildEntity}"> 
      <StackPanel Orientation="Horizontal"> 
       <TextBox Text="{Binding Name}"/> 
       <TextBox Text="{Binding Value}"/> 
      </StackPanel> 
     </DataTemplate> 

    </TreeView.Resources> 
</TreeView> 

ObservableCollection<ParentEntity> data = new ObservableCollection<ParentEntity>(); 
treeView.ItemsSource = data ; 

但我有結構如下(從庫)如何處理?謝謝。

+0

您是否考慮將實體包裝在提供您在問題的第一部分中描述的結構的對象中? – vkluge

+0

是的,這是第一個想法,但我不確定這是否正確。 – Feofilakt

+0

您可以嘗試使用IValueConverter調用一個方法,該方法將相應的子對象返回給父級,請參閱[這裏](http://stackoverflow.com/a/844946/4189791),但是這是明確的不是「正確的」做法。 – vkluge

回答

0

我不是真的建議,但我會解決你有 XAML

<StackPanel x:Name="root"> 
     <StackPanel.DataContext> 
      <vm:MainWindowViewModel></vm:MainWindowViewModel> 
     </StackPanel.DataContext> 
     <Button Command="{Binding AddRoot}">Add</Button> 
     <TreeView Height="400"> 
      <TreeView.Resources > 
       <Style TargetType="{x:Type TreeViewItem}"> 
        <Setter Property="IsExpanded" Value="True"> 
        </Setter> 
       </Style> 
       <vm:HierarchicalDataConverter x:Key="HierarchicalDataConverter"/> 
       <HierarchicalDataTemplate x:Key="ParentEntityTemplate" DataType="{x:Type vm:ParentEntity}" > 
        <HierarchicalDataTemplate.ItemsSource> 
         <MultiBinding Converter="{StaticResource HierarchicalDataConverter}" Mode="TwoWay"> 
          <Binding Mode="OneTime"></Binding> 
          <Binding Path="DataContext.Items" ElementName="root" ></Binding> 
          <Binding Path="DataContext.Items.Count" ElementName="root" ></Binding> 
         </MultiBinding> 
        </HierarchicalDataTemplate.ItemsSource> 
        <StackPanel Orientation="Horizontal"> 
         <TextBlock Text="{ Binding Name }"></TextBlock> 
         <Button Command="{Binding DataContext.AddLeafe, ElementName=root}" CommandParameter="{Binding}">Add item</Button> 
        </StackPanel> 
       </HierarchicalDataTemplate> 
       <DataTemplate x:Key="ChildEntityTemplate" DataType="{x:Type vm:ChildEntity}"> 
        <TextBlock Text="{Binding Name}"></TextBlock> 
       </DataTemplate> 
      </TreeView.Resources> 
      <TreeView.ItemsSource> 
       <Binding Path="RootItems"/> 
      </TreeView.ItemsSource> 
      <TreeView.ItemTemplateSelector> 
       <vm:ItemTemplateSelector> 
       </vm:ItemTemplateSelector> 
      </TreeView.ItemTemplateSelector> 
     </TreeView> 
    </StackPanel> 

VM命名空間

public class MainWindowViewModel : BindableBase 
    { 
     public ObservableCollection<object> Items { get; } = 
      new ObservableCollection<object>(new List<object>(new List<object> 
     { 
      new ParentEntity { UID = 1, Name = "Groop1" }, 
      new ChildEntity { ParentUID = 1, Name = "Item1" }, 
      new ParentEntity { UID = 2, Name = "Groop2" }, 
      new ChildEntity { ParentUID = 2, Name = "Item1" }, 
      new ChildEntity { ParentUID = 2, Name = "Item2" }, 
      new ChildEntity { ParentUID = 2, Name = "Item3" } 
     })); 

     public CollectionView RootItems { get; } 


     int count = 2; 
     public DelegateCommand AddRoot { get; } 

     public DelegateCommand<ParentEntity> AddLeafe { get; } 
     public MainWindowViewModel() 
     { 
      RootItems = new ListCollectionView(Items) { Filter = (item) => item is ParentEntity }; 

      AddRoot = new DelegateCommand(() => 
      { 
       Items.Add(new ParentEntity { UID = ++count ,Name= "Group"+count}); 
      }); 

      AddLeafe = new DelegateCommand<ParentEntity>((pe) => 
      { 
       Items.Add(new ChildEntity { ParentUID = pe.UID, Name = "Item" + count }); 
      }); 

     } 

    } 

    public class ParentEntity 
    { 
     public int UID { get; set; } 
     public string Name { get; set; } 
    } 

    public class ChildEntity 
    { 
     public int ParentUID { get; set; } 
     public string Name { get; set; } 
     public int Value { get; set; } 
    } 

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

      if (item is ParentEntity) 
      { 
       return element.FindResource("ParentEntityTemplate") as DataTemplate; 
      } 
      if (item is ChildEntity) 
      { 
       return element.FindResource("ChildEntityTemplate") as DataTemplate; 
      } 
      return null; 
     } 
    } 

    public class HierarchicalDataConverter : IMultiValueConverter 
    { 
     public object Convert(object[] value, Type targetType, object parameter, CultureInfo culture) 
     { 
      if (value[0] != null) 
      { 
       ParentEntity pe = value[0] as ParentEntity; 
       var items = value[1] as IEnumerable<object>; 

       return items.Where((item) => item is ChildEntity && (item as ChildEntity).ParentUID == pe.UID); 
      } 
      return null; 
     } 

     public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

的問題,這樣的問題是,它會重新創建所有的子節點