1

我想要这个动态类

class FooViewModel : INotifyPropertyChanged {

    private Dictionary<string, object> data = new Dictionary<string, object>();

    public void Set(string path, object value)
    {
        data[path]=value;
        NotifyPropertyChanged(path);
    }

    public object Get(string path)
    {
        if(data.ContainsKey(path)){
            return data[path];
        }else{
            return null;
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;

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

如果我将其设置为某些 WPF XAML 的 DataContext,我希望能够将数据绑定到two way bind其中的键。

<TextBox Text="{Bind Path=Foo}"/>
<TextBox Text="{Bind Path=Bar}"/>

在我的视图模型代码的某个地方,我将拥有

var vm = new FooViewModel();
vm.Set("Foo", "Yeah!");
vm.Set("Bar", "Booh!");

像这样进行自定义绑定有什么技巧?

4

1 回答 1

2

您可以从DynamicObject派生您的类或实现IDynamicMetaObjectProvider。这应该可以解决问题,因为 WPF 支持绑定到动态对象。

一个很好的例子是http://www.shujaat.net/2012/09/dynamicobject-wpf-binding.html

class ViewModelBase : DynamicObject, INotifyPropertyChanged
{
    #region Private Members

    private Dictionary<string, object> _dynamicProperties;

    #endregion Private Members

    #region Constructor

    public ViewModelBase(IEnumerable<string> propertyNames)
    {
        if (propertyNames == null)
        {
            throw new Exception("propertyNames is empty");
        }

        _dynamicProperties = new Dictionary<string, object>();
        propertyNames
            .ToList()
            .ForEach(propName => _dynamicProperties.Add(propName, null));
    }
    #endregion Constructor

    #region Public Methods

    public void SetPropertyValue(string propertyName, object value)
    {
        if (_dynamicProperties.ContainsKey(propertyName))
        {
            _dynamicProperties[propertyName] = value;
            OnPropertyChanged(propertyName);
        }
    }

    public object GetPropertyValue(string propertyName)
    {
        return _dynamicProperties.ContainsKey(propertyName) ? _dynamicProperties[propertyName] : null;
    }

    #endregion Public Methods

    #region DynamicObject Overriden Members

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        bool ret = base.TryGetMember(binder, out result);

        if (ret == false)
        {
            result = GetPropertyValue(binder.Name);
            if (result != null)
            {
                ret = true;
            }
        }

        return ret;
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        bool ret = base.TrySetMember(binder, value);

        if (ret == false)
        {
            SetPropertyValue(binder.Name, value);
            ret = true;
        }

        return ret;
    }

    #endregion DynamicObject Overriden Members

    #region INotifyPropertyChanged Implementation

    public event PropertyChangedEventHandler PropertyChanged = delegate { };
    private void OnPropertyChanged(string propertyName)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion INotifyPropertyChanged Implementation
}
于 2013-04-29T07:42:10.893 回答