WPF xaml自定义绑定标记

博客介绍了在xaml中绑定数组元素时,常规写法存在不利于阅读理解的问题,需知道元素在集合中的位置才能绑定。以班级中学生名字为例,阐述了自定义绑定标记的实现方法,还进行了属性变动通知测试,包括前台和后台改变数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当需要在xaml中绑定至数组中的某个元素时,常规写法不利于阅读理解,因为你必须得知道这个元素在集合中的位置才能进行绑定。下面以班级中学生的名字为例:
比如我想绑定至A班学号为1的学生的名字
常规写法:(前提是你得知道这个学生在集合中的第一个位置)

<TextBlock Text="{Binding Path=(local:Students.StuClassList)[0].StudentList[0].Name}" Width="100" Height="30"/>

想用自定义写法实现:

<TextBlock Text="{ local:StudentBinding A.1.Name}" Width="100" Height="30"/>

班级类:

    public class StuClass : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private string _classId;
        public string ClassID
        {
            get { return _classId; }
            set
            {
                _classId = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ClassID"));
            }
        }

        private ObservableCollection<Student> _studentList = new ObservableCollection<Student>();

        public ObservableCollection<Student> StudentList
        {
            get { return _studentList; }
            set { _studentList = value; 
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("StudentList"));
            }
        }
    }

学生类:

   public static class Students
    {

        public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged;

        private static ObservableCollection<Student> _student = new ObservableCollection<Student>();
        public static ObservableCollection<Student> StudentList
        {
            get { return _student; }
            set
            {
                _student = value;
                StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs("StudentList"));
            }
        }
        private static ObservableCollection<StuClass> _stuClassesList = new ObservableCollection<StuClass>();

        public static ObservableCollection<StuClass> StuClassList
        {
            get { return _stuClassesList; }
            set { _stuClassesList = value; 
                StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs("StuClassList"));
            }
        }
    }

静态全局班级集合:

public static class Students
    {
        public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged;
        private static ObservableCollection<StuClass> _stuClassesList = new ObservableCollection<StuClass>();

        public static ObservableCollection<StuClass> StuClassList
        {
            get { return _stuClassesList; }
            set
            {
                _stuClassesList = value;
                StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs("StuClassList"));
            }
        }
    }

自定义绑定标记:

public class StudentBinding : MarkupExtension
    {
        public string Path;
        public StudentBinding()
        {
            
        }
        public StudentBinding(string path)
        {
            Path = path;
        }
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
                var result = Path.Split('.');
                StuClass stuclass = Students.StuClassList.Single(s => s.ClassID == result[0]) as StuClass;
                Student stu = stuclass.StudentList.Single(s => s.ID == int.Parse(result[1])) as Student;
                Binding binding = new Binding();
                binding.Source = stu;
                binding.Path = new PropertyPath(result[2]);
                binding.Mode = BindingMode.TwoWay;
                binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                binding.NotifyOnSourceUpdated = true;
                binding.NotifyOnTargetUpdated = true;
                return binding.ProvideValue(serviceProvider);
        }
    }

在窗体构造函数中添加班级和学生:

 public MainWindow()
        {
            StuClass stuClass = new StuClass();
            stuClass.ClassID = "A";
            stuClass.StudentList.Add(new Student()
            {
                ID = 1,
                Name = "可莉"
            });
            stuClass.StudentList.Add(new Student()
            {
                ID = 2,
                Name = "派蒙"
            });
            stuClass.StudentList.Add(new Student()
            {
                ID = 3,
                Name = "七七"
            });
            stuClass.StudentList.Add(new Student()
            {
                ID = 4,
                Name = "早柚"
            });
            Students.StuClassList.Add(stuClass);
            InitializeComponent();
        }

xaml:

<Grid>
        <StackPanel VerticalAlignment="Center">
            <TextBox Text="{ local:StudentBinding A.1.Name}" Width="100" Height="30"/>
            <TextBlock Text="{ local:StudentBinding A.2.Name}" Width="100" Height="30"/>
            <TextBlock Text="{Binding Path=(local:Students.StuClassList)[0].StudentList[0].Name}" Width="100" Height="30"/>
            <Button Content="change" Width="60" Height="30" Click="Button_Click"/>
        </StackPanel>
    </Grid>

效果:
在这里插入图片描述
属性变动通知测试:
前台改变数据:
在这里插入图片描述
后台改变数据:

private void Button_Click(object sender, RoutedEventArgs e)
        {
            Students.StuClassList[0].StudentList[0].Name = "宵宫";
        }

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值