北海,要多想 2024-04-25 15:22 采纳率: 0%
浏览 5

WPF 的 转换器可以动态绑定吗

WPF 的 转换器可以动态绑定吗
TreeView的节点中的文本框使用了Converter={StaticResource IsLeafNodeConverter},但这个转换器只能对原来的数据有效,在程序运行后再往里添加节点,发现新增节点没有使用转换器。
试了下Dynamic Resources,直接跑不了
想问下有办法让新增的节点也能用转化器吗

img

img


<Window x:Class="WpfApp.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp"
        xmlns:conv="clr-namespace:WpfApp.ViewModels" 
        xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
        
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <conv:IsLeafNodeConverter x:Key="IsLeafNodeConverter" />
        <!-- 使用conv前缀引用转换器 -->
    </Window.Resources>
    <Grid>
        <TreeView ItemsSource="{Binding TreeNodes}" Margin="37,66,353,66">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Path=ChildNodes}">
                    <StackPanel  Orientation="Horizontal">
                        <TextBox Text="{Binding Path=NodeName, Mode=TwoWay}" Margin="0,0,5,0"></TextBox>
                        <TextBlock Text="权重"/>
                        <TextBox Text="{Binding Path=Weight, Mode=TwoWay}" Margin="0,0,5,0" >
                            <i:Interaction.Triggers>
                                <i:EventTrigger EventName="LostFocus">
                                    <i:InvokeCommandAction Command="{Binding Path=DataContext.updateScoreCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="{Binding Path=.}" />
                                </i:EventTrigger>
                            </i:Interaction.Triggers>
                        </TextBox>
                        <TextBlock Text="分数"/>
                        <!-- 静态资源(Static Resource),动态资源(Dynamic Resources)。这两者的区别是:静态资源在第一次编译后即确定其对象或值,之后不能对其进行修改。动态资源则是在运行时决定,当运行过程中真正需要时,才到资源目标中查找其值。因此,我们可以动态地修改它。由于动态资源的运行时才能确定其值,因此效率比静态资源要低。 -->
                        <!-- https://blog.csdn.net/yangwenxue1989/article/details/81385856 -->
                        <!-- https://www.itbaoku.cn/post/1981662.html -->
                        <TextBox Text="{Binding Path=Score, Mode=TwoWay}" Margin="0,0,5,0" IsEnabled="{Binding Path=. ,Converter={StaticResource IsLeafNodeConverter}}">
                            <i:Interaction.Triggers>
                                <i:EventTrigger EventName="LostFocus">
                                    <i:InvokeCommandAction Command="{Binding Path=DataContext.updateScoreCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="{Binding Path=.}" />
                                </i:EventTrigger>
                            </i:Interaction.Triggers>

                        </TextBox>
                        <Button Content="添加子指标" Command="{Binding Path=DataContext.addChildNodeCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="{Binding Path=.}"/>
                    </StackPanel>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
        <Button Content="测试双向绑定" Command="{Binding buttun_clickCommand}" HorizontalAlignment="Left" Margin="615,255,0,0" VerticalAlignment="Top" />
        <Button Content="添加一级指标" Command="{Binding addTopNodeCommand}" HorizontalAlignment="Left" Margin="371,36,0,0" VerticalAlignment="Top" />
        <TextBlock HorizontalAlignment="Left" Margin="37,36,0,0" TextWrapping="Wrap" VerticalAlignment="Top"><Run Language="zh-cn" Text="总分数"/><LineBreak/><Run Language="zh-cn"/></TextBlock>
        <TextBlock HorizontalAlignment="Left" Margin="92,36,0,0" TextWrapping="Wrap" Text="{Binding TotalScore}" VerticalAlignment="Top"/>
    </Grid>
</Window>

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using WpfApp.Models;

namespace WpfApp.ViewModels
{
    public class IsLeafNodeConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            // 检查传入的对象是否为TargetNode类型
            if (value!=null && value is TargetNode node)
            {
                Debug.WriteLine("判断该节点是否是叶子节点");
                
                // 如果节点有ChildNodes属性且为空,则为叶子节点
                return node.ChildNodes == null || node.ChildNodes.Count == 0;
                
            }
            return false;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}


  • 写回答

3条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-04-25 15:22
    关注

    引自免费微信小程序:皆我百晓生

    为了实现动态添加的节点也能够应用转换器,你需要确保以下几个方面:

    1. 当你添加新的TargetNode对象时,这些新对象应该被正确地添加到TreeNodes集合中,以便它们显示在TreeView中。
    2. 新增的节点应当继承自TargetNode类,并包含必要的属性,例如NodeNameWeightScore
    3. IsLeafNodeConverter需要能够处理新创建的对象。

    首先,确保你的MainViewModel包含了正确的数据结构和命令来添加新的节点。这里是一个简化版的MainViewModel示例,包含了用于添加新节点的命令:

    using System;
    using System.Collections.ObjectModel;
    using System.Windows.Input;
    
    public class MainViewModel
    {
        private ObservableCollection<TargetNode> _treeNodes = new ObservableCollection<TargetNode>();
        public ObservableCollection<TargetNode> TreeNodes { get => _treeNodes; set => _treeNodes = value; }
    
        public ICommand addChildNodeCommand { get; private set; }
        public ICommand addTopNodeCommand { get; private set; }
        public ICommand updateScoreCommand { get; private set; }
        public ICommand buttun_clickCommand { get; private set; }
    
        public MainViewModel()
        {
            addChildNodeCommand = new RelayCommand(param => AddChildNode((TargetNode)param));
            addTopNodeCommand = new RelayCommand(param => AddTopNode());
            updateScoreCommand = new RelayCommand(param => UpdateScore((TargetNode)param));
            buttun_clickCommand = new RelayCommand(param => TestBidirectionalBinding());
        }
    
        private void AddChildNode(TargetNode parent)
        {
            var newNode = new TargetNode { NodeName = "新添加的节点", Weight = 0, Score = 0 };
            parent.ChildNodes.Add(newNode);
            TreeNodes.Add(newNode); // 确保新的节点添加到了树视图的数据源中
        }
    
        private void AddTopNode()
        {
            var newNode = new TargetNode { NodeName = "新添加的一级指标", Weight = 0, Score = 0 };
            TreeNodes.Add(newNode);
        }
    
        private void UpdateScore(TargetNode node)
        {
            // 更新逻辑,例如计算总分等
        }
    
        private void TestBidirectionalBinding()
        {
            // 测试双向绑定逻辑
        }
    }
    

    接下来,确认你的TargetNode类定义了相应的属性:

    using System.Collections.ObjectModel;
    
    public class TargetNode
    {
        public string NodeName { get; set; }
        public int Weight { get; set; }
        public int Score { get; set; }
        public ObservableCollection<TargetNode> ChildNodes { get; } = new ObservableCollection<TargetNode>();
    
        // 其他属性和方法...
    }
    

    这样,当你执行添加操作时,新创建的节点将会被添加到TreeNodes集合中,并且会被转换器正确处理。这是因为IsLeafNodeConverter通过检查ChildNodes属性来判断一个节点是否是叶子节点,而新创建的节点会继承这个属性。

    如果你的问题仍然存在,可能是其他部分的代码有问题,或者与数据绑定相关的问题。请提供完整的项目结构和MainViewModel的相关代码,以便我能更精确地定位问题并提供解决方案。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 4月25日

悬赏问题

  • ¥15 BP神经网络控制倒立摆
  • ¥20 要这个数学建模编程的代码 并且能完整允许出来结果 完整的过程和数据的结果
  • ¥15 html5+css和javascript有人可以帮吗?图片要怎么插入代码里面啊
  • ¥30 Unity接入微信SDK 无法开启摄像头
  • ¥20 有偿 写代码 要用特定的软件anaconda 里的jvpyter 用python3写
  • ¥20 cad图纸,chx-3六轴码垛机器人
  • ¥15 移动摄像头专网需要解vlan
  • ¥20 access多表提取相同字段数据并合并
  • ¥20 基于MSP430f5529的MPU6050驱动,求出欧拉角
  • ¥20 Java-Oj-桌布的计算