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));
        }
    }
}

two way bindこれを DataContext として WPF XAML に設定すると、その中のキーにデータバインドできるようになります。

<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 に答える