You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF TreeView绑定二级ObservableCollection点击提交按钮无法显示层级数据如何解决

修复方案

你代码里存在多处绑定错误、逻辑错误和实例重复问题,按以下步骤修改即可正常运行:

1. 修复XAML代码

<UserControl x:Class="MCTv2.UI.LeftTreeView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:MCTv2.UI"
         xmlns:UIC="clr-namespace:MCTv2.UIController"
         xmlns:vm ="clr-namespace:MCTv2.Modules.ActionDefinition"
         xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
         mc:Ignorable="d" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch">
    <UserControl.DataContext>
        <UIC:AddChannelViewModel/>
    </UserControl.DataContext>
    <!-- 删掉重复的ViewModel实例声明,否则会出现两个独立的ViewModel实例数据不互通 -->
    <StackPanel>
        <TreeView ItemsSource="{Binding View}">
            <i:Interaction.Behaviors>
                <UIC:TreeViewBehavior/>
            </i:Interaction.Behaviors>
            <TreeView.Resources>
                <!-- 修复绑定路径:ItemsSource绑定DeviceObjects,Content绑定正确大小写的ChannelName -->
                <HierarchicalDataTemplate DataType="{x:Type vm:ChannelObject}"
                                      ItemsSource="{Binding DeviceObjects}">
                    <Label Content="{Binding ChannelName}"/>
                </HierarchicalDataTemplate>
                <!-- 新增DeviceObject的DataTemplate,否则设备节点不会显示正确名称 -->
                <HierarchicalDataTemplate DataType="{x:Type vm:DeviceObject}">
                    <Label Content="{Binding DeviceName}"/>
                </HierarchicalDataTemplate>
            </TreeView.Resources>
        </TreeView>
    </StackPanel>
</UserControl>

2. 修复Model层属性通知

你用了MvvmLight的ViewModelBase,自动属性不会触发UI变更通知,修改为标准通知属性:

public class ChannelObject : ViewModelBase
{
    private string _channelName;
    public string ChannelName
    {
        get => _channelName;
        set { _channelName = value; RaisePropertyChanged(); }
    }

    private ObservableCollection<DeviceObject> _deviceObjects = new ObservableCollection<DeviceObject>();
    public ObservableCollection<DeviceObject> DeviceObjects
    {
        get => _deviceObjects;
        set { _deviceObjects = value; RaisePropertyChanged(); }
    }
}

public class DeviceObject : ViewModelBase
{
    private string _deviceName;
    public string DeviceName
    {
        get => _deviceName;
        set { _deviceName = value; RaisePropertyChanged(); }
    }

    public UserTest userTests { get; set; } = new UserTest();
    public ConformanceTest confTests { get; set; } = new ConformanceTest();
}

3. 修复ViewModel逻辑错误

public class AddChannelViewModel : ViewModelBase
{
    private string channelName;
    private int numberofDev; // 改为int类型避免字符串拼接错误

    // 将treelist改为属性,WPF绑定不支持字段
    private ObservableCollection<ChannelObject> _treelist = new ObservableCollection<ChannelObject>();
    public ObservableCollection<ChannelObject> View 
    { 
        get => _treelist;
        set { _treelist = value; RaisePropertyChanged(); }
    }
    
    // SelectedItem改为通知属性
    private ChannelObject _selectedItem;
    public ChannelObject SelectedItem 
    { 
        get => _selectedItem;
        set { _selectedItem = value; RaisePropertyChanged(); }
    }

    private ChannelObject Channel
    {
        get => new ChannelObject()
        {
            ChannelName = channelName,
            DeviceObjects = new ObservableCollection<DeviceObject>()
            {
                new DeviceObject()
                {
                    DeviceName = $"device {numberofDev}",
                    confTests = new ConformanceTest(),
                    userTests = new UserTest()
                },
                new DeviceObject()
                {
                    DeviceName = $"device {numberofDev+1}",
                    confTests = new ConformanceTest(),
                    userTests = new UserTest()
                }
            }
        };
    }

    public AddChannelViewModel()
    {
        AddChannelCommand = new RelayCommand<object[]>(AddTreeNode);
        ClosePopupCommand = new RelayCommand<object>(ClosePopup);
    }

    private void AddTreeNode(object[] parameter)
    {
        channelName = parameter[0].ToString();
        if (string.IsNullOrWhiteSpace(channelName)) return;
        // 把输入的设备数量转为int
        if(!int.TryParse(parameter[1].ToString(), out numberofDev)) return;

        if (parameter[2] is Window win)
        {
            win.Close();
        }

        if (SelectedItem == null) 
            View.Add(Channel); 
        else 
            // 删掉没用的devs属性,直接new DeviceObject添加
            SelectedItem.DeviceObjects.Add(new DeviceObject()
            {
                DeviceName = $"device {numberofDev}"
            });
    }

    private void ClosePopup(object parameter)
    {
        if (parameter is Window win) 
        { 
            win.Close(); 
        }
    }

    public ICommand AddChannelCommand { get; set; }
    public ICommand ClosePopupCommand { get; set; }
}

4. 优化TreeViewBehavior容错

public class TreeViewBehavior : Behavior<TreeView>
{
    protected override void OnAttached()
    {
        AssociatedObject.SelectedItemChanged += AssociatedObject_SelectedItemChanged;
    }

    private void AssociatedObject_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        if (sender is not TreeView tv || tv.DataContext is not AddChannelViewModel vm) return;
        // 仅当选中的是通道节点时赋值,避免选中设备节点时SelectedItem为null
        vm.SelectedItem = tv.SelectedItem as ChannelObject;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.SelectedItemChanged -= AssociatedObject_SelectedItemChanged;
        base.OnDetaching();
    }
}

修改完成后即可实现:未选中节点时点击提交新增根通道节点,选中通道节点时点击提交为该通道新增子设备节点,层级结构正常展示。


内容的提问来源于stack exchange,提问作者h1d3r00t

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 00:06:05