首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在设置PropertyDescriptor后向ICustomTypeDescriptor添加附加DataContext

如何在设置PropertyDescriptor后向ICustomTypeDescriptor添加附加DataContext
EN

Stack Overflow用户
提问于 2014-01-21 00:12:06
回答 1查看 1.4K关注 0票数 0

Qeustion:

在设置了PropertyDescriptor之后,是否有可能向ICustomTypeDescriptorPropertyDescriptorCollection中添加一个附加的DataConext

详细信息:

我正在创建一个实现ICustomTypeDescriptor的新类,其目标是在运行时动态地向该类添加新属性,并将它们绑定到WPF应用程序。

例如,用户可以通过脚本语言定义一个新属性(例如。在应用程序运行时,我希望XAML能够绑定到该属性。

我遇到的问题是,如果在设置了DataContext之后添加了一个属性,到XAML的绑定就不能工作;它不会尝试调用关联的PropertyDescriptor.GetValue方法。

我相信这个问题是,在将DataContext设置为我的ICustomTypeDescriptor后不久,它的ICustomTypeDescriptor.GetProperties实现就被调用了,此时我为所有已知的属性创建了PropertyDescriptor。然后,我随后添加了新的属性,但是没有能力为它们添加新的PropertyDescriptor

代码:

我在这里删减了一些代码,以使它更容易阅读,删除了大量的锅炉板的东西。

本例中的思想是,第一个文本字段绑定到动态创建的属性,该属性是在构造期间定义的,而第二个文本字段绑定到一个在单击Button之前不存在的属性。

单击按钮时创建的属性只有在我将DataBound设置为新的东西时才能正确地获取DataContext。

代码语言:javascript
复制
public class MyCustomType : ICustomTypeDescriptor, INotifyPropertyChanged
{
    Dictionary<string, object> Properties = new Dictionary<string, object>();

    public event PropertyChangedEventHandler PropertyChanged;

    public MyCustomType()
    {
        Properties.Add("CustomProp", "What up, world?");
    }

    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

    public void CreateOrSetProperty(string name, object val)
    {
        Properties[name] = val;
        NotifyPropertyChanged(name);
    }

    PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
    {
        List<PropertyDescriptor> props = new List<PropertyDescriptor>();

        foreach (KeyValuePair<string, object> entry in Properties)
        {
            props.Add(new MyCustomTypePropertyDescriptor(entry.Key, attributes));
        }

        return new PropertyDescriptorCollection(props.ToArray());
    }

    PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
    {
        return ((ICustomTypeDescriptor)this).GetProperties(null);
    }

    class MyCustomTypePropertyDescriptor : PropertyDescriptor
    {
        public MyCustomTypePropertyDescriptor(string name, Attribute[] attrs)
            : base(name, attrs)
        {
        }

        public override object GetValue(object component)
        {
            return ((MyCustomType)component).Properties[Name];
        }

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

         public override void SetValue(object component, object value)
        {
            ((MyCustomType)component).Properties[Name] = value;
        }
    }
}

public partial class Page5
{
    public Page5()
    {
        this.InitializeComponent();
    }

    private void BtnAddProperty_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        // A static resource defined in XAML used as the DataContext for both text blocks.
        MyCustomType c = Resources["MyCustomTypeData"] as MyCustomType;

        // Create a new property which is already being referenced in a DataBind in XAML but 
        // prior to this function being called, did not exist.
        c.CreateOrSetProperty("AnotherProp", "Another Property!");

        // If I clear the DataContext and set it back to the previous value it triggers 
        // ICustomTypeDescriptor.GetProperties to get called again, and the property gets
        // Bound. If I don't do this, it fails.
        //MyTextBlock2.DataContext = null;
        //MyTextBlock2.DataContext = c;
    }
}

代码语言:javascript
复制
<Page.Resources>
    <WpfApplication1:MyCustomType x:Key="MyCustomTypeData"/>
</Page.Resources>

<Grid x:Name="LayoutRoot">
    <StackPanel HorizontalAlignment="Left" VerticalAlignment="Top">
        <TextBlock DataContext="{StaticResource MyCustomTypeData}" x:Name="MyTextBlock" HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding CustomProp}" VerticalAlignment="Top" FontSize="32" Background="Black" Foreground="White"/>
        <TextBlock DataContext="{StaticResource MyCustomTypeData}" x:Name="MyTextBlock2" HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding AnotherProp}" VerticalAlignment="Top" FontSize="32" Background="Black" Foreground="White"/>
        <Button x:Name="BtnAddProperty" Content="Add Additional Property" Click="BtnAddProperty_Click"/>
    </StackPanel>
</Grid>

EN

回答 1

Stack Overflow用户

发布于 2014-01-21 02:03:12

我不完全理解你的问题。但是,我想,在绑定表达式中使用字典可能是问题的一部分。在我看来,将在xaml中绑定的集合应该是从ObservableCollection中删除的类型,以便拥有在集合更改时通知视图的能力。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21246731

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档