2014-10-01 43 views
1

只有頂級節點可以反映後面的更改,但其節點不能。有任何想法嗎?謝謝!在下面的代碼中,它應該在同一時間添加新的經理和新員工 。TreeView的子節點無法反映綁定中的更改

模型
public class Employee 
{ 
    public Guid EmployeeId { get; set; } 
    public string EmployeeName { get; set; } 
} 

public class Manager 
{ 
    public Guid ManagerId { get; set; } 
    public string ManagerName { get; set; } 
    public IEnumerable<Employee> Employees { get; set; } 
} 

的ViewModels
public class TreeWindowViewModel : INotifyPropertyChanged 
{ 
    private List<Employee> employeeList = new List<Employee>(); 
    private List<Manager> managerList = new List<Manager>(); 

    public TreeWindowViewModel() 
    { 
     //Create fake data for testing 
     employeeList.Add(new Employee() { EmployeeId = Guid.NewGuid(), EmployeeName = "Adam" }); 
     employeeList.Add(new Employee() { EmployeeId = Guid.NewGuid(), EmployeeName = "Benson" }); 
     employeeList.Add(new Employee() { EmployeeId = Guid.NewGuid(), EmployeeName = "Cooker" }); 
     employeeList.Add(new Employee() { EmployeeId = Guid.NewGuid(), EmployeeName = "Denny" }); 
     employeeList.Add(new Employee() { EmployeeId = Guid.NewGuid(), EmployeeName = "Ellis" }); 

     //Create ObservableCollection object 
     employees = new ObservableCollection<Employee>(employeeList); 

     //Create 2 managers and make 
     Manager manager1 = new Manager() 
     { 
      ManagerId = Guid.NewGuid(), 
      ManagerName = "Frank", 
      Employees = new List<Employee>(employeeList) 
     }; 

     Manager manager2 = new Manager() 
     { 
      ManagerId = Guid.NewGuid(), 
      ManagerName = "Green", 
      Employees = new List<Employee>(employeeList) 
     }; 

     managerList.Add(manager1); 
     managerList.Add(manager2); 

     managers = new ObservableCollection<Manager>(managerList); 

    } 

    private ObservableCollection<Manager> managers; 
    public ObservableCollection<Manager> Managers 
    { 
     get 
     { 
      return managers; 
     } 
     set 
     { 
      managers = value; 

      OnPropertyChanged(new PropertyChangedEventArgs("Managers")); 
     } 
    } 

    private ObservableCollection<Employee> employees; 
    public ObservableCollection<Employee> Employees 
    { 
     get 
     { 
      return employees; 
     } 
     set 
     { 
      employees = value; 

      OnPropertyChanged(new PropertyChangedEventArgs("Employees")); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    public void OnPropertyChanged(PropertyChangedEventArgs e) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, e); 
     } 
    } 
} 

XAML
<Window x:Class="BindingTests.TreeWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:m="clr-namespace:BindingTests.Models" 
     Title="TreeWindow" Height="300" Width="300"> 
    <Window.Resources> 
     <HierarchicalDataTemplate ItemsSource="{Binding Path=Employees}" DataType="{x:Type m:Manager}"> 
      <TextBlock Text="{Binding Path=ManagerName}"/> 
     </HierarchicalDataTemplate> 
     <HierarchicalDataTemplate DataType="{x:Type m:Employee}"> 
      <TextBlock Text="{Binding Path=EmployeeName}"/> 
     </HierarchicalDataTemplate> 
    </Window.Resources> 
    <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="*"/> 
      <ColumnDefinition Width="Auto"/> 
     </Grid.ColumnDefinitions> 
     <TreeView ItemsSource="{Binding Managers, Mode=OneWay, NotifyOnSourceUpdated=True}" Grid.Column="0"> 
      <TreeView.Resources> 
       <Style TargetType="Label"> 
        <Setter Property="Margin" Value="0"/> 
        <Setter Property="Padding" Value="0"/> 
       </Style> 
       <Style TargetType="TreeViewItem"> 
        <Setter Property="Margin" Value="0"/> 
        <Setter Property="Padding" Value="0"/> 
       </Style> 
      </TreeView.Resources> 
     </TreeView> 
     <StackPanel Grid.Column="1"> 
      <Button Content="Click me to add a manager" Click="Button_Click" Height="30"/> 
     </StackPanel> 
    </Grid> 
</Window> 

XAML.CS
namespace BindingTests 
    { 
    /// <summary> 
    /// Interaction logic for TreeWindow.xaml 
    /// </summary> 
    public partial class TreeWindow : Window 
    { 
     public TreeWindow() 
     { 
      InitializeComponent(); 

      this.DataContext = new TreeWindowViewModel(); 
     } 

     private void Button_Click(object sender, RoutedEventArgs e) 
     { 
      TreeWindowViewModel ds = this.DataContext as TreeWindowViewModel; 
      if (ds != null) 
      { 
       ds.Managers.Add(new Manager() { ManagerId = Guid.NewGuid(), ManagerName = "New Manager" }); 
       ds.Employees.Add(new Employee() { EmployeeId = Guid.NewGuid(), EmployeeName = "New Employee"}); 
      } 
     } 
    } 
} 

Initial UI

enter image description here

回答

1

你沒有得到預期的效果,主要的原因是因爲你添加Employeepublic ObservableCollection<Employee> Employees,並沒有在那裏的UI是綁定的。你真的看到你的初始清單Managers綁定到TreeView。該<HierarchicalDataTemplate ItemsSource="{Binding Path=Employees}" ...實際上是在尋找Manager.Employees,所以在你點擊按鈕,如果你這樣做:

if (ds != null) 
{ 
    ds.Managers.Add(new Manager() { ManagerId = Guid.NewGuid(), ManagerName = "New Manager" }); 
    ds.Managers[0].Employees.Add(new Employee() { EmployeeId = Guid.NewGuid(), EmployeeName = "New Employee"}); 
} 

那麼你會看到「新員工」下添加經理「坦率」。所以我認爲你的代碼是可以的,它只是你如何添加它導致問題。

您的下一個問題可能是「我該如何知道是誰來添加員工?」這就是您要在TreeWindowViewModel中創建public object SelectedItem並將其綁定到可添加到TreeView的依賴屬性,因爲TreeViewSelectedItem是隻讀的非DP。然後,您就能夠調用是這樣的:

if(ds.SelectedItem is Manager) 
{ 
    (ds.SelectedItem as Manager).Employees.Add(...); 
} 

但現在我們走出的範圍,可能會引發新太問題在未來的你。

相關問題