添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

问题描述:

在开发过程中,项目使用了 Treeview 控件。在之前的实现过程中,控件树的源数据为 List<T> 类型,绑定在属性 ItemSource 上。若想实时更新 List 上的属性变化,需在类型T的定义过程中实现 INotifyPropertyChanged 接口,并在需要通知属性值变更的对应属性内实现类似 RaisePropertyChanged() 的方法。且在原来的开发中,没有实现对 List 内成员数量变化的时候的实时通知。

原实现方法:

Treeview.ItemSource = null;
Treeview.ItemSource = TreeviewNodes;

通过对控件绑定的源数据的“手动”更新去更新前台UI,不方便也很不科学

原因分析:

我们先看看 List 的定义:

    public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, IEnumerable, IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>
    {...}

可以看出, List 本身是没有继承类似 Notify 的接口的,因此本身也无法提供属性改变的通知行为。

解决方案:

经过查找资料后,发现 .Net 提供了这样的一个集合类型 ObservableCollection<T>

	public class ObservableCollection<T> : Collection<T>, INotifyCollectionChanged, INotifyPropertyChanged
    {...}

该类继承了继承了Collection, INotifyCollectionChanged, INotifyPropertyChanged,其中:

  • Collection:为泛型集合提供基类。

  • INotifyCollectionChanged:将集合的动态更改通知给侦听器,例如,何时添加和移除项或者重置整个集合对象。

  • INotifyPropertyChanged:向客户端发出某一属性值已更改的通知。

所以再ObservableCollection这个类的方法,对数据的操作很少,重点放在了当自己本事变化的时候(不管是属性,还是集合)会调用发出通知的事件。

下面贴出修改后的 Treeview 控件的实现代码

后台 ViewModel 中的代码:

using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using sdm.Model;
namespace sdm.ViewModel
    public class MainViewModel : ViewModelBase
		private ObservableCollection<NodeViewModel> treeviewNodes;
        /// <summary>
        /// TreeView
        /// </summary>
        public ObservableCollection<NodeViewModel> TreeviewNodes
            get => treeviewNodes;
            set => Set(ref treeviewNodes, value);
        public MainViewModel()
            if (IsInDesignMode)
                // Code runs in Blend --> create design time data.
                // Code runs "for real"
            TreeviewNodes = new ObservableCollection<NodeViewModel>();
            //这里为了测试新增了5个测试节点
            for (int i = 0; i < 5; i++)
                RtuModel rtu = new RtuModel();
                rtu.RtuNum = i;
                rtu.Address = $"测试节点{i}";
                NodeViewModel node = new NodeViewModel()
                     Rtu = rtu,                     
                TreeviewNodes.Add(node);

前台 xaml 中的代码:

<TreeView Grid.Row="1" x:Name="treeview" Margin="10,5,10,0" ItemsSource="{Binding TreeviewNodes, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
	<TreeView.Resources>
		<HierarchicalDataTemplate  DataType="{x:Type vmmain:NodeViewModel}" ItemsSource="{Binding}">
			<StackPanel x:Name="SPanel" Orientation="Horizontal" Margin="0,2,0,2">
				<Image Height="15" Width="15" Source="{Binding ConIcon.Source, Mode=TwoWay}"/>
				<TextBlock x:Name="NodeText" Text="{Binding Title, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>									
			</StackPanel>
		</HierarchicalDataTemplate>
 </TreeView>

运行后效果:
运行结果
实时新增节点:
运行结果
完美实现需求

参考资料:

[1] WPF MVVM-TreeView数据源添加了节点,UI没有刷新
[2] C# ObservableCollection和List的区别
[3] WPF中使用MVVM模式实现可动态检索的Treeview

比如要在test1234节点下新建子节点,首先要选中test1234节点,添加成功后,根据test1234结点的TID去后台请求对应子节点数据,实现动态刷新。删除节点类似。 三、代码实现 1、初始化时必须设置配置
本文样例通过NuGet获取MvvmLight框架,实现了TreeView的加载,节点添加和节点删除功能,其中节点加载的方式与常见的迭代方式不同,这里使用了字典的方式,提供了一种生成结构数据对象的方式,如果有遇到TreeView数据加载卡顿的同学,可以考虑尝试使用这种方式。 本文主要代码如下(源码可见文章最后), 首先定义了节点接口,包含组成结构数据的基本属性 public inter...
<TreeView ItemsSource="{Binding Path=Model.Clusters}" ItemTemplate="{StaticResource ClusterTemplate}" SelectedItem="{Binding Path=Mod
TreeView控件可在结构中显示分层数据,其中的项可以展开和折叠。它可以包含多种类型的控件,如Button、Lable、Image等控件,可以通过绑定到数据源并使用HieratchicalDataTemplate对象来填充其。可以修改默认ControlTemplate以使控件具有独特的外观。 这里举一个完整的TreeView实例来进行说明。本节主要实现自定义控件样式+数据源绑定+动态添加父...
最近开发redis可视化ui,连到了阿里云上的redis,这个redis的hash动辄好几百条数据,拿到后写到QTableview中。测试良好。 但测试一段时间后,点了几十条hash,拿到了几十条hash数据,QTableview也更新了几十次,在进行其他操作的时候,出现了程序崩溃。 于是就想,是不是发生了内存泄漏。 假设有一个QTableview,名叫table 先看下面的代码,功能是清空TableView void clearTreeView(){ ui->view->setM 你多观察一下,会发现有一个短暂的白屏。 一、启动白屏优化   首先我们处理白屏的问题,首先我想的是更改一下启动页的样式,之前是一片白,现在我改成绿色的,绿才有安全感,要想代码过得去,样式就得带点绿,手动滑稽。 那么首先在colors.xml中增加一个颜色值: <color name="green">#2E
MVVM Light 是一个开源的 MVVM (Model-View-ViewModel) 框架,用于开发 Windows 平台的应用程序。它的主要优点在于简洁易用、轻量级,支持 WPF、Silverlight、Windows Phone、Windows 8/8.1、Windows 10 UWP 等平台。 下面是一个简单的 MVVM Light 使用教程: 1. 首先,安装 MVVM Light 框架。可以通过 NuGet 包管理器安装,命令如下: Install-Package MvvmLight 2. 在项目中添加一个 ViewModel 类。这个类会绑定到 View 上。 3. 编写 View 的 XAML 代码。在根元素上添加 DataContext 属性绑定到 ViewModel。 4. 编写 ViewModel 类中的逻辑代码。这些代码会更新 View 的状态。 5. 在 View 的 XAML 代码中添加绑定。例如,将一个文本框的 Text 属性绑定到 ViewModel 中的一个属性上。 6. 在 ViewModel 中使用命令来处理 View 上的用户交互。 7. 按照需要使用其他 MVVM Light 的功能,例如消息传递、导航、本地化等。 最后,我需要提醒你 MVVM 是一种模式,不同的框架可能有不同的实现,每种框架都有它的优缺点,需要根据自己的需求来选择合适的框架. 防止其它进程占用 [code=plain] using (FileStream fStream = new FileStream(filePath, System.IO.FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) [/code]