2015-02-20 3 views
0

Я использую шаблон MVVM в своем приложении. У меня есть этот (упрощенный вариант) классы VM:WPF Treeview сложная иерархия

public class MainModule_VM 
{ 
    ... 

    public ObservableCollection<Module2601_VM> ListModules{...} 

    ... 
} 

public class Module2601_VM 
{ 
    ... 

    public string GatewayName {...} 
    public string FirmwareVersion{...} 
    public string IPAddress{...} 
    public string NbIoms{...} 
    public ObservableCollection<Module2610_VM> ListModules{...} 
    public ObservableCollection<ComPort_VM> ListCOM{...} 

    ... 
} 

public class Module2610_VM 
{ 
    ... 

    public string ModuleName{...} 

    ... 
} 

public class ComPort_VM 
{ 
    ... 

    public string ComPortName{...} 

    ... 
} 

Так, один Module2601_VM содержит несколько свойств, а также список Module2610_VM и ComPort_VM объектов.

У меня есть один список объектов Module2601_VM в классе MainModule_VM.

Я хочу, чтобы связать эту коллекцию Module2601 и это суб-элементов в Treeview, с этой иерархии:

Шлюзы:

  • Шлюз # 0
    • IP
    • микропрограмм
    • NbIoms
    • ListModules
      • Модуль # 0
      • Модуль # 1
      • ...
    • ListCOM
      • COM # 1
      • ...

Моя проблема заключается в том, что я получаю иерархию в порядке, но не могу выбрать подпозиции. Он принимает любой элемент шлюза и все его дети как один большой элемент. Я знаю, что это из-за моего itemTemplate, но я не могу решить эту проблему. Вот XAML (DataContext набор в код-сзади):

<TreeView Name="treeView1" > 
    <TreeViewItem Header="Gateways" ItemsSource="{Binding ListMM}"> 
     <TreeViewItem.ItemTemplate> 
      <DataTemplate> 
       <TreeViewItem Header="{Binding GatewayName, Mode=OneWay}" IsExpanded="True"> 
        <TreeViewItem Header="{Binding Path=Gateway.IPAddress, Mode=OneWay}"/> 
        <TreeViewItem Header="{Binding Path=Gateway.FirmwareVersion, Mode=OneWay}"/> 
        <TreeViewItem Header="{Binding Path=Gateway.NumberIoms, Mode=OneWay}"/> 
        <TreeViewItem Header="MIOs" ItemsSource="{Binding ListModules, Mode=OneWay}"> 
         <TreeViewItem.ItemTemplate> 
          <DataTemplate> 
           <TextBlock Text="{Binding ModuleName, Mode=OneWay}" /> 
          </DataTemplate> 
         </TreeViewItem.ItemTemplate> 
        </TreeViewItem> 
        <TreeViewItem Header="COM" ItemsSource="{Binding ListCOM, Mode=OneWay}"> 
         <TreeViewItem.ItemTemplate> 
          <DataTemplate> 
           <TextBlock Text="{Binding Path=PortCom.ComP, Mode=OneWay}"/> 
          </DataTemplate> 
         </TreeViewItem.ItemTemplate> 
        </TreeViewItem> 
       </TreeViewItem>  
      </DataTemplate> 
     </TreeViewItem.ItemTemplate> 
    </TreeViewItem>     
</TreeView> 

С этим я не могу выбрать подпункты, это выглядит следующим образом: picture

Теперь следующий пример, где я только есть один пункт Module2601_VM в моей TreeView, это все хорошо, и я могу выбрать отдельные элементы:

<TreeView Name="treeView2"> 
    <TreeViewItem Header="Gateways"> 
     <TreeViewItem Header="{Binding GatewayName, Mode=OneWay}"> 
      <TreeViewItem Header="{Binding Path=IPAddress, Mode=OneWay}"/> 
      <TreeViewItem Header="{Binding Path=FirmwareVersion, Mode=OneWay}"/> 
      <TreeViewItem Header="{Binding Path=NumberIoms, Mode=OneWay}"/> 
      <TreeViewItem Header="MIOs" ItemsSource="{Binding ListModules, Mode=OneWay}"> 
       <TreeViewItem.ItemTemplate> 
        <DataTemplate> 
         <TextBlock Text="{Binding ModuleName, Mode=OneWay}" /> 
        </DataTemplate> 
       </TreeViewItem.ItemTemplate> 
      </TreeViewItem> 
      <TreeViewItem Header="COM" ItemsSource="{Binding ListCOM, Mode=OneWay}"> 
       <TreeViewItem.ItemTemplate> 
        <DataTemplate> 
         <TextBlock Text="{Binding Path=ComPortName, Mode=OneWay}"/> 
        </DataTemplate> 
       </TreeViewItem.ItemTemplate> 
      </TreeViewItem> 
     </TreeViewItem> 
    </TreeViewItem> 
</TreeView> 

Как я могу иметь свой TreeView быть как treeView1 но с treeView2 выбора functionnality? HierarchicalDataTemplate здесь не работает, потому что дочерние элементы имеют различный тип. Спасибо.

ответ

0

Чтобы достичь представленного вами представления TreeView, на мой взгляд, вы должны использовать «неявный» DataTemplate mechanism и HierarchicalDataTemplate.

Что касается первого пункта я бы создать пару классов, чтобы иметь «простой» тип для ваших наблюдаемых коллекций:

public class Module2610_VMCollection : ObservableCollection<Module2610_VM> 
{ 
} 

public class ComPort_VMCollection : ObservableCollection<ComPort_VM> 
{ 
} 

тогда Module2601_VM класс станет:

public class Module2601_VM 
{ 
    /* ... */ 

    public string GatewayName {get; set;} 
    public string FirmwareVersion { get; set; } 
    public string IPAddress { get; set; } 
    public string NbIoms { get; set; } 
    public Module2610_VMCollection ListModules { get; set; } 
    public ComPort_VMCollection ListCOM { get; set; } 

    /* ... */ 
} 

Действительно ваш ViewModel не отражает структуру, которую вы хотите показать в пользовательском интерфейсе, поэтому, я думаю, вам нужен класс, чтобы «описать» детей вашего модуля2601_VM. Нечто подобное:

public class Module2601_VMChildrenDescriptor : IEnumerator, IEnumerable 
{ 
    private readonly Module2601_VM module2601_VM; 
    private int i = -1; 

    public Module2601_VMChildrenDescriptor(Module2601_VM module2601_VM) 
    { 
     this.module2601_VM = module2601_VM; 
    } 

    public object Current 
    { 
     get 
     { 
      switch (i) 
      { 
       case 0: 
        return module2601_VM.GatewayName; 
       case 1: 
        return module2601_VM.FirmwareVersion; 
       case 2: 
        return module2601_VM.IPAddress; 
       case 3: 
        return module2601_VM.NbIoms; 
       case 4: 
        return module2601_VM.ListModules; 
       case 5: 
        return module2601_VM.ListCOM; 
      } 

      return null; 
     } 
    } 

    public bool MoveNext() 
    { 
     return ++i < 6; 
    } 

    public void Reset() 
    { 
     i = -1; 
    } 

    public IEnumerator GetEnumerator() 
    { 
     return this; 
    } 
} 

Так полный вид модели будет:

public class Module2601_VM 
{ 
    private Module2601_VMChildrenDescriptor module2601_VMChildrenDescriptor; 
    public Module2601_VM() 
    { 
     module2601_VMChildrenDescriptor = new Module2601_VMChildrenDescriptor(this); 
     ListModules = new Module2610_VMCollection(); 
     ListCOM = new ComPort_VMCollection(); 
    } 

    public string GatewayName {get; set;} 
    public string FirmwareVersion { get; set; } 
    public string IPAddress { get; set; } 
    public string NbIoms { get; set; } 
    public Module2610_VMCollection ListModules { get; set; } 
    public ComPort_VMCollection ListCOM { get; set; } 

    public IEnumerable Children 
    { 
     get 
     { 
      return module2601_VMChildrenDescriptor; 
     } 
    } 
} 

Теперь вам нужно просто объявить DataTemplates в вашем XAML как ресурсы управления TreeView:

<TreeView ItemsSource="{Binding Path=ListModules}"> 
    <TreeView.Resources> 
     <HierarchicalDataTemplate DataType="{x:Type local:Module2601_VM}" ItemsSource="{Binding Path=Children, Mode=OneWay}"> 
      <TextBlock Text="Module2601_VM" Margin="1" /> 
     </HierarchicalDataTemplate> 
     <DataTemplate DataType="{x:Type sys:String}"> 
      <TextBlock Text="{Binding Mode=OneWay}" Margin="1" /> 
     </DataTemplate> 
     <DataTemplate DataType="{x:Type local:Module2610_VM}"> 
      <TextBlock Text="{Binding Path=ModuleName, Mode=OneWay}" Margin="1" /> 
     </DataTemplate> 
     <HierarchicalDataTemplate DataType="{x:Type local:Module2610_VMCollection}" ItemsSource="{Binding Mode=OneWay}"> 
      <TextBlock Text="ListModules" Margin="1" /> 
     </HierarchicalDataTemplate> 

     <DataTemplate DataType="{x:Type local:ComPort_VM}"> 
      <TextBlock Text="{Binding Path=ComPortName, Mode=OneWay}" Margin="1" /> 
     </DataTemplate> 
     <HierarchicalDataTemplate DataType="{x:Type local:ComPort_VMCollection}" ItemsSource="{Binding Mode=OneWay}"> 
      <TextBlock Text="ComPort_VM" Margin="1" /> 
     </HierarchicalDataTemplate> 
    </TreeView.Resources> 
</TreeView> 

Теперь каждый узел TreeView можно выбрать. Надеюсь, это поможет.

+0

Это сработало как прелесть при первой попытке! Большое спасибо! –

+0

Я счастлив, что это помогло! Добро пожаловать –