2017-09-19 6 views
1

これは重複している可能性がありますが、私にとって解決策はありません。だから私は、これらのプロパティを持つクラスTechnikを持っている:ObservableCollectionをツリービューに階層的にバインドするにはどうすればいいですか?

public class Technik 
{ 
    public bool checkedTe { get; set; } 

    public int TechnikID { get; set; } 

    public string anlagengruppe { get; set; } 

    public string techniktyp { get; set; } 

    public string anlage { get; set; } 

    public string bemerkung { get; set; } 
} 

は今、私は216行とDataTableを持っており、各行は次のように私のObservableCollection<Technik>に追加されTechnik対象になっている:

foreach (DataRow dr in dtTechnik.Rows) 
{ 
    Technik technik = new Technik(); 

    technik.checkedTe = (bool)dr.ItemArray[0]; 
    technik.TechnikID = (int)dr.ItemArray[1]; 
    technik.anlagengruppe = (string)dr.ItemArray[2]; 
    technik.techniktyp = (string)dr.ItemArray[3]; 
    technik.anlage = (string)dr.ItemArray[4]; 
    technik.bemerkung = (string)dr.ItemArray[5]; 

    TechnikCollection.Add(technik); 
} 

* anlagengruppe 
    * techniktyp 
      *anlage 
      * TechnikID 

今私はどこにもなってないよ、ので、多分Y:私は私のようなObservableCollectionが結合したいです私が助けてくれる人がいます。 実際の私のツリービューは次のようになります。

<TreeView x:Name="treeView" HorizontalAlignment="Left" Height="850" Margin="10,0,0,0" VerticalAlignment="Top" Width="464" 
      ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Visible" ItemsSource="{Binding TechnicTable}"> 
    <TreeView.ItemTemplate> 
     <HierarchicalDataTemplate ItemsSource="{Binding TechnicTable}"> 
      <TextBlock Text="{Binding Path=anlagengruppe}" /> 
      <HierarchicalDataTemplate.ItemTemplate> 
       <DataTemplate> 
        <TextBlock Text="{Binding techniktyp}" /> 
       </DataTemplate> 
      </HierarchicalDataTemplate.ItemTemplate> 
     </HierarchicalDataTemplate> 
    </TreeView.ItemTemplate> 
</TreeView> 

編集: はたぶん、あなたのいくつかは、いくつかのより多くのコードがあり、私のツリービューItemsSourceが正しいコレクションは、これは正しいものされないと思われるところIコレクションを変更する。

+0

'HierarchicalDataTemplate'は' Technik'モデルには対応していません。そのクラスには 'TechnicTable'コレクションはありませんが、そのプロパティにバインドしようとしています。 – dymanoid

+0

EDITの最初のおかげで...私の問題は、Technik Modelのプロパティを正しくバインドする方法を知らないということです。これはすべて試行錯誤しています。どのようにこれらのプロパティを正しくバインドするのですか? – user8574993

答えて

0

私はこのデザインに懐疑的です。単一のオブジェクトとそのプロパティ値がそのオブジェクトに階層的な構造を持っているかのように提示することは、ユーザーにとって便利で役立ちます。

視覚的なの構造をユーザーインターフェイスに課すことは、TreeViewを使わずに簡単に行うことができます。例:あなたはTreeViewを使用する必要がありますし、あなたは、コレクションが変更されると更新するビューのために必要な場合、あなたが中間のコレクションを使用してそれを達成することができ、私には思われる、と述べた

class TableItem 
{ 
    public string Property1 { get; set; } 
    public string Property2 { get; set; } 
    public string Property3 { get; set; } 

    public TableItem() { } 

    public TableItem(string property1, string property2, string property3) 
    { 
     Property1 = property1; 
     Property2 = property2; 
     Property3 = property3; 
    } 
} 

class ViewModel 
{ 
    public ObservableCollection<TableItem> TableItems { get; } = new ObservableCollection<TableItem>(); 
} 
<Window x:Class="TestSO46300831HiearchicalObservable.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:l="clr-namespace:TestSO46300831HiearchicalObservable" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.DataContext> 
    <l:ViewModel> 
     <l:ViewModel.TableItems> 
     <l:TableItem Property1="Item #1, property #1" 
        Property2="Item #1, property #2" 
        Property3="Item #1, property #3"/> 
     <l:TableItem Property1="Item #2, property #1" 
        Property2="Item #2, property #2" 
        Property3="Item #2, property #3"/> 
     <l:TableItem Property1="Item #3, property #1" 
        Property2="Item #3, property #2" 
        Property3="Item #3, property #3"/> 
     </l:ViewModel.TableItems> 
    </l:ViewModel> 
    </Window.DataContext> 

    <Window.Resources> 
    <DataTemplate DataType="{x:Type l:TableItem}"> 
     <StackPanel> 
     <TextBlock Text="{Binding Property1}"/> 
     <TextBlock Text="{Binding Property1}" Margin="10,0,0,0"/> 
     <TextBlock Text="{Binding Property1}" Margin="20,0,0,0"/> 
     </StackPanel> 
    </DataTemplate> 
    </Window.Resources> 

    <StackPanel> 
    <ListBox ItemsSource="{Binding TableItems}"/> 
    </StackPanel> 
</Window> 

INotifyCollectionChangedを実装しています(ObservableCollection<T>を継承し、元のコレクションを追跡するだけで簡単に実行できます)。中間コレクションが必要なので、元の単一オブジェクトアイテムからTreeViewクラスで使用できる階層アイテムタイプにアイテムを変換できます。例:

class HierarchicalTableItem 
{ 
    public string Text { get; } 
    public IReadOnlyList<HierarchicalTableItem> Items { get; } 

    public HierarchicalTableItem(string text, HierarchicalTableItem child = null) 
    { 
     Text = text; 
     Items = child != null ? new[] { child } : null; 
    } 
} 

class ViewModel 
{ 
    public ICommand AddCommand { get; } 
    public ICommand InsertCommand { get; } 
    public ICommand RemoveCommand { get; } 

    public int Index { get; set; } 

    public ObservableCollection<TableItem> TableItems { get; } = new ObservableCollection<TableItem>(); 

    public ViewModel() 
    { 
     AddCommand = new DelegateCommand(() => TableItems.Add(_CreateTableItem())); 
     InsertCommand = new DelegateCommand(() => TableItems.Insert(Index, _CreateTableItem())); 
     RemoveCommand = new DelegateCommand(() => TableItems.RemoveAt(Index)); 
    } 

    private int _itemNumber; 

    private TableItem _CreateTableItem() 
    { 
     _itemNumber = (_itemNumber < TableItems.Count ? TableItems.Count : _itemNumber) + 1; 

     return new TableItem(
      $"Item #{_itemNumber}, property #1", 
      $"Item #{_itemNumber}, property #2", 
      $"Item #{_itemNumber}, property #3"); 
    } 
} 

class ConvertingObservableCollection<T> : ObservableCollection<object> 
{ 
    private readonly IValueConverter _converter; 
    private readonly ObservableCollection<T> _collection; 

    public ConvertingObservableCollection(IValueConverter converter, ObservableCollection<T> collection) 
    { 
     _converter = converter; 
     _collection = collection; 
     _ResetItems(); 
     _collection.CollectionChanged += _OnCollectionChanged; 
    } 

    private void _OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     switch (e.Action) 
     { 
      case NotifyCollectionChangedAction.Add: 
       _AddItems(e); 
       break; 
      case NotifyCollectionChangedAction.Move: 
       _RemoveItems(e); 
       _AddItems(e); 
       break; 
      case NotifyCollectionChangedAction.Remove: 
       _RemoveItems(e); 
       break; 
      case NotifyCollectionChangedAction.Replace: 
       _ReplaceItems(e); 
       break; 
      case NotifyCollectionChangedAction.Reset: 
       _ResetItems(); 
       break; 
     } 
    } 

    private void _ReplaceItems(NotifyCollectionChangedEventArgs e) 
    { 
     for (int i = 0; i < e.NewItems.Count; i++) 
     { 
      this[i] = _Convert(e.NewItems[i]); 
     } 
    } 

    private void _AddItems(NotifyCollectionChangedEventArgs e) 
    { 
     for (int i = 0; i < e.NewItems.Count; i++) 
     { 
      Insert(i + e.NewStartingIndex, _Convert(e.NewItems[i])); 
     } 
    } 

    private void _RemoveItems(NotifyCollectionChangedEventArgs e) 
    { 
     for (int i = e.OldItems.Count - 1; i >= 0; i--) 
     { 
      RemoveAt(i + e.OldStartingIndex); 
     } 
    } 

    private void _ResetItems() 
    { 
     Clear(); 
     foreach (T t in _collection) 
     { 
      Add(_Convert(t)); 
     } 
    } 

    private object _Convert(object value) 
    { 
     return _converter.Convert(value, typeof(T), null, null); 
    } 
} 

class TableItemHierarchicalConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     TableItem tableItem = value as TableItem; 

     if (tableItem == null) 
     { 
      return Binding.DoNothing; 
     } 

     return new HierarchicalTableItem(tableItem.Property1, 
        new HierarchicalTableItem(tableItem.Property2, 
         new HierarchicalTableItem(tableItem.Property3))); 
    } 

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

class ConvertingCollectionConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     IValueConverter converter = parameter as IValueConverter; 

     if (converter == null || value == null || 
      value.GetType().GetGenericTypeDefinition() != typeof(ObservableCollection<>)) 
     { 
      return Binding.DoNothing; 
     } 

     Type resultType = typeof(ConvertingObservableCollection<>).MakeGenericType(value.GetType().GenericTypeArguments); 

     return Activator.CreateInstance(resultType, converter, value); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 
<Window x:Class="TestSO46300831HiearchicalObservable.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:l="clr-namespace:TestSO46300831HiearchicalObservable" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.DataContext> 
    <l:ViewModel> 
     <l:ViewModel.TableItems> 
     <l:TableItem Property1="Item #1, property #1" 
        Property2="Item #1, property #2" 
        Property3="Item #1, property #3"/> 
     <l:TableItem Property1="Item #2, property #1" 
        Property2="Item #2, property #2" 
        Property3="Item #2, property #3"/> 
     <l:TableItem Property1="Item #3, property #1" 
        Property2="Item #3, property #2" 
        Property3="Item #3, property #3"/> 
     </l:ViewModel.TableItems> 
    </l:ViewModel> 
    </Window.DataContext> 

    <Window.Resources> 
    <l:ConvertingCollectionConverter x:Key="convertingCollectionConverter1"/> 
    <l:TableItemHierarchicalConverter x:Key="tableItemConverter1"/> 
    </Window.Resources> 

    <ScrollViewer> 
    <StackPanel> 
     <UniformGrid Columns="4"> 
     <Button Content="Add" Command="{Binding AddCommand}"/> 
     <Button Content="Insert" Command="{Binding InsertCommand}"/> 
     <Button Content="Remove" Command="{Binding RemoveCommand}"/> 
     <TextBox Text="{Binding Index}"/> 
     </UniformGrid> 
     <TreeView ItemsSource="{Binding TableItems, 
       Converter={StaticResource convertingCollectionConverter1}, 
       ConverterParameter={StaticResource tableItemConverter1}}"> 
     <TreeView.ItemTemplate> 
      <HierarchicalDataTemplate ItemsSource="{Binding Items}"> 
      <TextBlock Text="{Binding Text}"/> 
      </HierarchicalDataTemplate> 
     </TreeView.ItemTemplate> 
     </TreeView> 
    </StackPanel> 
    </ScrollViewer> 
</Window> 

この選択肢は3つの主要なクラスに依存している:これは、元のコレクションを見て、その元のコレクションの現在の状態に応じて変換された項目を提示する作業を行う

  • ConvertingObservableCollection<T> —。
  • TreeViewにバインドする目的で、元のコレクションをConvertingObservableCollection<T>オブジェクトに変換します。
  • TableItemHierarchicalConverter —これは、個々の元のアイテムオブジェクトをTreeViewの表示に適したオブジェクトの階層に変換します。

もちろん、各テーブル項目の階層を表すために使用される単純なコンテナクラスHierarchicalTableItemもあります。

最終的に、覚えておくべきキーがTreeViewのために、あなた単一HierarchicalDataTemplate要素がツリーの各レベルを提示する方法を定義するために使用することができるように、再帰的な性質を持っているアイテムを、提示しなければならないということです。つまり、1つのデータ項目にテンプレートのItemsSourceに使用できるいくつかのプロパティが必要です。テンプレート自体は同じタイプのデータ項目のコレクションです。

+0

あなたの反応がありがとう!昨日私は自分のデータモデルが駄目だと気づいたので、私はそれを拡張しました - そして今私は階層的なやり方をすることができます。あなたの時間と説明に感謝します! – user8574993

+0

@ user8574993:https://stackoverflow.com/help/someone-answers –

関連する問題