WPF C# TreeView 绑定后实时更新

项目原方案用的是比较简单的方案,绑定后,要更新显示,对绑定类先清除子节点再加上新的节点,更新到.net6后发现运行中内存消耗不断增加。经排查问题出在这一段,怀疑childNodes.Clear()后,原引用没有释放。原因不明,有了解的高手请指点。

fatherNode.ChildNodes.Clear();
foreach (Weather v in weathers.Values) //weathers是数据来源
{
    SubEq subNode = new()
    {
        Display = v.Config.Dislplay + ":" + v.StrValue//显示新内容
    };
    fatherNode.ChildNodes.Add(subNode);
}

为解决以上问题,采样INotifyPropertyChanged接口方案。

前端代码:

        <TreeView x:Name="TvRealTimeData" Padding="1,1,5,1">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding ChildNodes}">
                    <TextBlock Text="{Binding Display}"/>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
            <TreeView.ItemContainerStyle>
                <Style TargetType="{x:Type TreeViewItem}">
                    <Setter Property="IsExpanded" Value="True"></Setter>
                </Style>
            </TreeView.ItemContainerStyle>
        </TreeView>

后台代码:

    /// <summary>
    /// 绑定ViewTree,记录设备状态
    /// </summary>
    private readonly List<Equipment> EquipmentTree = new();

    public WpfMain()
    {
        //初始化EquipmentTree省略
        InitializeComponent();
        TvRealTimeData.ItemsSource = EquipmentTree;//绑定界面树
    }


    /// <summary>
    /// 控件绑定EquipmentTree,更新属性即可
    /// </summary>
    /// <param name="weathers"></param>
    private void ShowRealData(Weathers weathers)
    {
        Equipment fatherNode = EquipmentTree.Find(x => x.Address == weathers.Address);
        try
        {
            foreach (var n in fatherNode.ChildNodes)
            {
                var v = weathers.Values.Find(x => x.Config.Index == n.Index);
                n.Display = v.Config.Dislplay + ":" + v.StrValue;
            }
        }
        catch (Exception)
        {

        }
    }

要绑定的Equipmnet类

public class Equipment
{
    public byte Address { get; set; }
    public string Display { get; set; }


    public ObservableCollection<SubEq> ChildNodes { get; set; } = new();
}

/// <summary>
/// 设备下的子设备,用于TreeView数据展示,有命令返回时动态删除重建,不适合保存其他数据
/// </summary>
public class SubEq : INotifyPropertyChanged
{
    private string _Display;

    public uint Index { get; set; }

    public string Display { get => _Display; set => UpdateProperty(ref _Display, value); }

    public List<SubEq> ChildNodes { get; set; } = new();//未使用,仅防止编译器提示

    /// <summary>
    /// 属性改变事件句柄
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// 属性改变事件
    /// </summary>
    /// <param name="propertyName">已更改属性的名称,null参数指示所有属性已更改</param>
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private void UpdateProperty<T>(ref T properValue, T newValue, [CallerMemberName] string propertyName = "")
    {
        if (Equals(properValue, newValue))
        {
            return;
        }
        properValue = newValue;

        OnPropertyChanged(propertyName);
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现WPF ComboBox下拉绑定Treeview功能,可以参考以下步骤: 1. 创建一个ViewModel,其中包含一个ObservableCollection用于绑定ComboBox的ItemsSource,同时也包含一个ObservableCollection用于绑定TreeView的ItemsSource。 2. 在ViewModel的构造函数中,初始化ComboBox的ItemsSource和TreeView的ItemsSource。 3. 在ComboBox的SelectedIndexChanged事件中,获取选中项的子节点数据,将其添加到TreeView的ItemsSource中。 4. 在XAML中,使用ComboBox和TreeView控件,并将它们的ItemsSource绑定到ViewModel中的相应属性。 下面是一个简单的示例代码: ViewModel: ```c# public class MainViewModel : INotifyPropertyChanged { private ObservableCollection<string> _comboBoxItemsSource; private ObservableCollection<string> _treeViewItemsSource; public MainViewModel() { // 初始化ComboBox的ItemsSource ComboBoxItemsSource = new ObservableCollection<string> { "Node1", "Node2", "Node3" }; // 初始化TreeView的ItemsSource TreeViewItemsSource = new ObservableCollection<string> { "Root" }; } public ObservableCollection<string> ComboBoxItemsSource { get => _comboBoxItemsSource; set { _comboBoxItemsSource = value; OnPropertyChanged(); } } public ObservableCollection<string> TreeViewItemsSource { get => _treeViewItemsSource; set { _treeViewItemsSource = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } ``` XAML: ```xml <Window.DataContext> <local:MainViewModel /> </Window.DataContext> <Grid> <ComboBox ItemsSource="{Binding ComboBoxItemsSource}" SelectedIndex="0" Width="100" /> <TreeView ItemsSource="{Binding TreeViewItemsSource}" Margin="0,30,0,0"> <TreeView.ItemTemplate> <HierarchicalDataTemplate ItemsSource="{Binding Children}"> <TextBlock Text="{Binding Name}" /> </HierarchicalDataTemplate> </TreeView.ItemTemplate> </TreeView> </Grid> ``` 在ComboBox的SelectedIndexChanged事件中,获取选中项的子节点数据,将其添加到TreeView的ItemsSource中。 ```c# private void ComboBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e) { var selectedItem = e.AddedItems[0] as string; // 根据选中项获取子节点数据 var children = GetChildren(selectedItem); // 将子节点数据添加到TreeView的ItemsSource中 var root = TreeViewItemsSource[0]; if (root == "Root") { TreeViewItemsSource.Clear(); TreeViewItemsSource.Add(new Node { Name = "Root", Children = children }); } else { var node = TreeViewItemsSource[0] as Node; node.Children = children; } } private ObservableCollection<Node> GetChildren(string selectedItem) { // TODO: 根据选中项获取子节点数据 return new ObservableCollection<Node> { new Node { Name = $"{selectedItem}-1" }, new Node { Name = $"{selectedItem}-2" }, new Node { Name = $"{selectedItem}-3" } }; } public class Node { public string Name { get; set; } public ObservableCollection<Node> Children { get; set; } } ``` 以上示例代码仅供参考,实现过程中可能需要根据具体需求进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值