c# - WPF 数据绑定(bind) - "Custom Type Descriptor"示例

标签 c# wpf data-binding binding

我看到几个人说 WPF 可以使用“自定义类型描述符”来实现“更改通知”。

我知道如何进行更改通知的方法是:

object.GetBindingExpression(Bound.property).UpdateTarget();

或者让我的对象实现 INotifiyPropertyChanged

我看到评论说自定义类型描述符也可以工作,但是没有人给出一个很好的例子来说明它是如何工作的。我现在要的是那个例子(IE 是 WPF 数据绑定(bind)和通过自定义类型描述符更新的一个很好的例子。)

最佳答案

这是一个非常简单的例子。

Window1.xaml:

<Window x:Class="CTDExample.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <TextBlock>Name:</TextBlock>
        <TextBox Grid.Column="1" Text="{Binding Name}"/>

        <TextBlock Grid.Row="1">Age:</TextBlock>
        <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Age}"/>

        <TextBlock Grid.Row="2" Grid.ColumnSpan="2">
            <TextBlock.Text>
                <MultiBinding StringFormat="{}{0} is {1} years old.">
                    <Binding Path="Name"/>
                    <Binding Path="Age"/>
                </MultiBinding>
            </TextBlock.Text>
        </TextBlock>
    </Grid>
</Window>

Window1.xaml.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows;

namespace CTDExample
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            var ctd = new CTD();
            ctd.AddProperty("Name");
            ctd.AddProperty("Age");
            DataContext = ctd;
        }
    }

    public class CTD : CustomTypeDescriptor
    {
        private static readonly ICollection<PropertyDescriptor> _propertyDescriptors = new List<PropertyDescriptor>();

        public void AddProperty(string name)
        {
            _propertyDescriptors.Add(new MyPropertyDescriptor(name));
        }

        public override PropertyDescriptorCollection GetProperties()
        {
            return new PropertyDescriptorCollection(_propertyDescriptors.ToArray());
        }

        public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
        {
            return GetProperties();
        }

        public override EventDescriptorCollection GetEvents()
        {
            return null;
        }

        public override EventDescriptorCollection GetEvents(Attribute[] attributes)
        {
            return null;
        }
    }

    public class MyPropertyDescriptor : PropertyDescriptor
    {
        private readonly IDictionary<object, object> _values;

        public MyPropertyDescriptor(string name)
            : base(name, null)
        {
            _values = new Dictionary<object, object>();
        }

        public override bool CanResetValue(object component)
        {
            throw new NotImplementedException();
        }

        public override Type ComponentType
        {
            get { throw new NotImplementedException(); }
        }

        public override object GetValue(object component)
        {
            object value = null;
            _values.TryGetValue(component, out value);
            return value;
        }

        public override bool IsReadOnly
        {
            get { return false; }
        }

        public override Type PropertyType
        {
            get { return typeof(object); }
        }

        public override void ResetValue(object component)
        {
            throw new NotImplementedException();
        }

        public override void SetValue(object component, object value)
        {
            var oldValue = GetValue(component);

            if (oldValue != value)
            {
                _values[component] = value;
                OnValueChanged(component, new PropertyChangedEventArgs(base.Name));
            }
        }

        public override bool ShouldSerializeValue(object component)
        {
            throw new NotImplementedException();
        }

        public override void AddValueChanged(object component, EventHandler handler)
        {
            // set a breakpoint here to see WPF attaching a value changed handler
            base.AddValueChanged(component, handler);
        }
    }
}

关于c# - WPF 数据绑定(bind) - "Custom Type Descriptor"示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1834454/

相关文章:

c# - 如何等到 await/async 方法完成

wpf - 绑定(bind)到 CompositeCollection 中的单个元素

c# - 如何在不丢失原始颜色轨迹的情况下使背景颜色动画为新颜色并返回?

wpf - 显示工具提示时 DataGridCell 内容消失

silverlight - 如何为绑定(bind)到 viewmodel 属性的 silverlight 文本 block 提供设计时间值?

javascript - KnockoutJS IF 绑定(bind) - 保留 DOM

c# - XPath 查询不起作用

c# - 从设备读取短信的正则表达式

c# - 使用 LINQ 集合中的条件更新字符串

android - 驼峰包名时的数据绑定(bind)库