Только узлы верхнего уровня могут отражать изменения, но их узлы не могут. Есть идеи? Благодарю! В следующем коде он должен добавить нового менеджера и нового сотрудника в одно и то же время.
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; }
}
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);
}
}
}
<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>
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"});
}
}
}
}
Основная причина, по которой вы не получаете ожидаемых результатов, заключается в том, что вы добавляете Employee
в public ObservableCollection<Employee> Employees
, и нет, где в пользовательском интерфейсе это ограничение. Что вы действительно видите, ваш первоначальный список 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"});
}
то вы увидите "Новый сотрудник", добавленный под менеджером "Фрэнк". Поэтому я думаю, что ваш код в порядке, его просто, как вы добавляете его, что вызывает проблемы.
Следующий вопрос, вероятно, будет следующим: "Ну, как я должен знать, к кому добавить сотрудника?" и что там, где вы захотите создать public object SelectedItem
в TreeWindowViewModel
и привязать его к свойству зависимостей, которое вы могли бы добавить в TreeView
, поскольку TreeView
SelectedItem
является не-DP для чтения. Тогда вы сможете называть что-то вроде:
if(ds.SelectedItem is Manager)
{
(ds.SelectedItem as Manager).Employees.Add( ... );
}
но теперь мы выходим из сферы действия и можем поднять новый вопрос SO в будущем для вас.