C# ObservableCollection 没有出现在 MVVM 的 TreeView 中
C# ObservableCollection dosen't appear in TreeView by MVVM
所以我有一个包含 Name
、Code
、Id
和 List
的集合,节点类型为 ServiceTypeDto
,就像这个模型:
public class ServiceTypeDto
{
public long Id
public string Code
public string Name
public List<ServiceTypeDto> ChildrenList
}
我有一个方法 returns ServiceTypeDto
的列表,像这样:
我有一个 ChildernList
暴露了 ServiceTypeDto
s。
这就是我在 ViewModel 中尝试执行此操作的方式:
using System.Collections.Generic;
using System.Collections.ObjectModel;
using ServiceTypeService.Dto;
using ServiceTypeService.Interface;
using ShowServiceType.Interfaces;
using ShowServiceType.Utils;
namespace ShowServiceType.ViewModel
{
class MainWindowViewModel : ViewModelBase
{
public string _name, _code;
public long _id;
public List<ServiceTypeDto> _childrenList = new List<ServiceTypeDto>();
/// <summary>
/// Create Services for work
/// </summary>
ILogService Log => Service.CreateLog();
IExceptionHandler ExceptionHandler => Service.CreateExeptionHandler();
IServiceType ServiceType => Service.CreateGetServiceType();
public ObservableCollection<ServiceTypeDto> _servicesCollection;
public MainWindowViewModel()
{
ServiceConfig.Initialization();
var _services = ServiceType.GetServiceTypesTree();
_servicesCollection = new ObservableCollection<ServiceTypeDto>();
//This is convert to ObservableCollection my List<> =)
foreach (var item in _services)
_servicesCollection.Add(item);
}
public long ID
{
get => _id;
set
{
_id = value;
OnPropertyChanged("ID");
}
}
public string Code
{
get => _code;
set
{
_code = value;
OnPropertyChanged("Code");
}
}
public string Name
{
get => _name;
set
{
_name = value;
OnPropertyChanged("Name");
}
}
public List<ServiceTypeDto> Children
{
get => _childrenList;
set
{
_childrenList = value;
OnPropertyChanged("Children");
}
}
}
}
我的 ViewModelBase
类型:
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged( string propname ) => PropertyChanged?.Invoke(this , new PropertyChangedEventArgs(propname));
}
我的主要代码隐藏 window:
public MainWindow()
{
InitializeComponent();
ServiceConfig.Initialization();
DataContext = new MainWindowViewModel();
}
最后这是视图的XAML。
<Grid Grid.Row="1">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Visible">
<TreeView>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Children}">
<StackPanel FlowDirection="LeftToRight" Orientation="Horizontal">
<TextBlock Text="{Binding ID}" />
<TextBlock Text="{Binding Code}" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</ScrollViewer>
</Grid>
ObservableCollection
没有出现在 TreeView
中。怎么了?
您的视图和视图模型中存在多个问题:
TreeView
没有绑定任何东西,将它的ItemSource
绑定到Children
,否则不会显示任何项目
HierarchicalDataTemplate
的 ItemsSource
必须绑定到您的 ServiceTypeDto
中的子集合,即 ChildrenList
,而不是 Children
- 您没有填充
Children
集合(或其后备集合 _childrenList
),因此它是空的。
- 您将项目添加到
_servicesCollection
,但它也未被使用
ServiceTypeDto
未实现 INotifyPropertyChanged
,因此属性更改不会反映在用户界面中
ServiceTypeDto
中的 ChildrenList
不是 ObservableCollection
,因此添加或删除项目也不会反映在用户界面中
您应该考虑对 属性 使用 Children
和对支持字段使用 _children
这样的命名约定,以提高代码的可读性,参考 here关于 C# 中的命名。
1) 好的,我在 View 上绑定了我的 TreeView.ItemSource
到 ChildrenList
2) 我不明白我如何将集合 ServiceTypeDto
中的 ChildList
绑定到我的 ObserveCollection
,我如何理解索引我 select 在 UI ?
public List<ServiceTypeDto> ChildrenList
{
get => _servicesCollection[0].ChildrenList; // ? index ?
set
{
_servicesCollection[0].ChildrenList = value; // ? 0 ?
OnPropertyChanged("ChildrenList");
}
}
public string Name
{
get => _servicesCollection[0].Name; // ? 0 ?
set
{
_servicesCollection[0].Name = value; // ?
OnPropertyChanged("Name");
}
}
其他属性必须知道要从 _servicesCollection[index].Name
请求正确数据的索引?
3) 我无法根据任务条件将 ServiceTypeDto
中的 ChildrenList
更改为 ObserveCollection
out off dll。
这只是参考。
在此之后,我不知道如何使用 0 索引!
但是只工作第一个节点不会出现在 subList
中的其他列表
<Grid Grid.Row="1">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Visible">
<TreeView ItemsSource="{Binding Path=ChildrenList}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=ChildrenList}">
<StackPanel FlowDirection="LeftToRight" Orientation="Horizontal">
<TextBlock Text="{Binding ID}" />
<TextBlock Text="{Binding Code}" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</ScrollViewer>
</Grid>
所以我有一个包含 Name
、Code
、Id
和 List
的集合,节点类型为 ServiceTypeDto
,就像这个模型:
public class ServiceTypeDto
{
public long Id
public string Code
public string Name
public List<ServiceTypeDto> ChildrenList
}
我有一个方法 returns ServiceTypeDto
的列表,像这样:
我有一个 ChildernList
暴露了 ServiceTypeDto
s。
这就是我在 ViewModel 中尝试执行此操作的方式:
using System.Collections.Generic;
using System.Collections.ObjectModel;
using ServiceTypeService.Dto;
using ServiceTypeService.Interface;
using ShowServiceType.Interfaces;
using ShowServiceType.Utils;
namespace ShowServiceType.ViewModel
{
class MainWindowViewModel : ViewModelBase
{
public string _name, _code;
public long _id;
public List<ServiceTypeDto> _childrenList = new List<ServiceTypeDto>();
/// <summary>
/// Create Services for work
/// </summary>
ILogService Log => Service.CreateLog();
IExceptionHandler ExceptionHandler => Service.CreateExeptionHandler();
IServiceType ServiceType => Service.CreateGetServiceType();
public ObservableCollection<ServiceTypeDto> _servicesCollection;
public MainWindowViewModel()
{
ServiceConfig.Initialization();
var _services = ServiceType.GetServiceTypesTree();
_servicesCollection = new ObservableCollection<ServiceTypeDto>();
//This is convert to ObservableCollection my List<> =)
foreach (var item in _services)
_servicesCollection.Add(item);
}
public long ID
{
get => _id;
set
{
_id = value;
OnPropertyChanged("ID");
}
}
public string Code
{
get => _code;
set
{
_code = value;
OnPropertyChanged("Code");
}
}
public string Name
{
get => _name;
set
{
_name = value;
OnPropertyChanged("Name");
}
}
public List<ServiceTypeDto> Children
{
get => _childrenList;
set
{
_childrenList = value;
OnPropertyChanged("Children");
}
}
}
}
我的 ViewModelBase
类型:
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged( string propname ) => PropertyChanged?.Invoke(this , new PropertyChangedEventArgs(propname));
}
我的主要代码隐藏 window:
public MainWindow()
{
InitializeComponent();
ServiceConfig.Initialization();
DataContext = new MainWindowViewModel();
}
最后这是视图的XAML。
<Grid Grid.Row="1">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Visible">
<TreeView>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Children}">
<StackPanel FlowDirection="LeftToRight" Orientation="Horizontal">
<TextBlock Text="{Binding ID}" />
<TextBlock Text="{Binding Code}" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</ScrollViewer>
</Grid>
ObservableCollection
没有出现在 TreeView
中。怎么了?
您的视图和视图模型中存在多个问题:
TreeView
没有绑定任何东西,将它的ItemSource
绑定到Children
,否则不会显示任何项目HierarchicalDataTemplate
的ItemsSource
必须绑定到您的ServiceTypeDto
中的子集合,即ChildrenList
,而不是Children
- 您没有填充
Children
集合(或其后备集合_childrenList
),因此它是空的。 - 您将项目添加到
_servicesCollection
,但它也未被使用 ServiceTypeDto
未实现INotifyPropertyChanged
,因此属性更改不会反映在用户界面中ChildrenList
不是ObservableCollection
,因此添加或删除项目也不会反映在用户界面中
ServiceTypeDto
中的 您应该考虑对 属性 使用 Children
和对支持字段使用 _children
这样的命名约定,以提高代码的可读性,参考 here关于 C# 中的命名。
1) 好的,我在 View 上绑定了我的 TreeView.ItemSource
到 ChildrenList
2) 我不明白我如何将集合 ServiceTypeDto
中的 ChildList
绑定到我的 ObserveCollection
,我如何理解索引我 select 在 UI ?
public List<ServiceTypeDto> ChildrenList
{
get => _servicesCollection[0].ChildrenList; // ? index ?
set
{
_servicesCollection[0].ChildrenList = value; // ? 0 ?
OnPropertyChanged("ChildrenList");
}
}
public string Name
{
get => _servicesCollection[0].Name; // ? 0 ?
set
{
_servicesCollection[0].Name = value; // ?
OnPropertyChanged("Name");
}
}
其他属性必须知道要从 _servicesCollection[index].Name
请求正确数据的索引?
3) 我无法根据任务条件将 ServiceTypeDto
中的 ChildrenList
更改为 ObserveCollection
out off dll。
这只是参考。
在此之后,我不知道如何使用 0 索引! 但是只工作第一个节点不会出现在 subList
中的其他列表<Grid Grid.Row="1">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Visible">
<TreeView ItemsSource="{Binding Path=ChildrenList}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=ChildrenList}">
<StackPanel FlowDirection="LeftToRight" Orientation="Horizontal">
<TextBlock Text="{Binding ID}" />
<TextBlock Text="{Binding Code}" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</ScrollViewer>
</Grid>