我能不加思索地这么做吗?

本文关键字:不加思索 | 更新日期: 2023-09-27 18:09:43

对于一个包含Person对象的PersonName的六个组件的演示,我添加了一个扩展和一个'迷你视图模型' (PersonNamePropertyTextBox),以减少重复代码并方便数据绑定。

在父视图模型的构造函数中,我创建了这些迷你视图模型,如

   public PimDetailVm(Person person, ..) 
    {
        LastName = new PersonNamePropertyTextBox(
            () => Model.GetPersonName().LastName, v => this.UpdatePersonNameProperty(pn => pn.LastName, v))
        {
            Label = PeopleResources.LastName_Label
        };
        FirstName = new PersonNamePropertyTextBox(
            () => Model.GetPersonName().FirstName, v => this.UpdatePersonNameProperty(pn => pn.FirstName, v))
        {
            Label = PeopleResources.FirstName_Label
        };
        ... etc.
    }
    public PersonNamePropertyTextBox LastName { get; private set; }
    public PersonNamePropertyTextBox FirstName { get; private set; }

我想真正的现在能够做的是传递当前属性,即LastName和标签值,并让迷你视图模型设置适当的Getter/Setter委托,如:

LastName = new PersonNamePropertyTextBox(vm=>LastName, PeopleResources.LastName_Label);

我正在努力如何做到这一点。什么好主意吗?

扩展(句柄更新模型中的PersonName)

    public static void UpdatePersonNameProperty(this PimDetailVm vm, Expression<Func<PersonName, object>> propertyExpression, string value)
    {
        var pn = vm.Model.GetPersonName();
        var pnProps = pn.GetType().GetProperties();
        var subj = ExprHelper.GetPropertyName(propertyExpression);
        var subjProp = pnProps.Single(pi => pi.Name.Equals(subj));
        var currentVal = subjProp.GetValue(pn, null);
        // split if there is nothing to update
        if(currentVal==null && value==null) return;
        if (currentVal != null && currentVal.Equals(value)) return;
        // update the property
        var capitalized = value == null ? null : value.Capitalize();
        subjProp.SetValue(pn, capitalized, null);
        // update the model
        vm.Model.SetName(pn);
        // broadcast the update
        vm.NotifyOfPropertyChange(subj, value);
    }

某个PersonName属性的迷你视图模型

public class PersonNamePropertyTextBox : TextBoxActionData
{
    public PersonNamePropertyTextBox(Func<string> getterFunc, Action<string> setterAction) {
        if (getterFunc == null) throw new ArgumentNullException("getterFunc");
        if (setterAction == null) throw new ArgumentNullException("setterAction");
        GetterFunc = getterFunc;
        SetterAction = setterAction;
    }
}

我能不加思索地这么做吗?

尝试实现一个绑定器类来管理绑定。在本例中,我使用了PropertyBinding

public class PropertyBinding
{
    public static PropertyBinding To(ViewModel vm, Name name, string label)
    {
        return new PropertyBinding { ViewModel = vm, Getter = new Func<string>(delegate() { return name.Value; }), Setter = new Action<string>(delegate(string value) { name.Value = value; }), Label = label };
    }
    public string Label { get; set; }
    public ViewModel ViewModel { get; set; }
    public Func<string> Getter { get; set; }
    public Action<string> Setter { get; set; }
    public string Value
    {
        get { return this.Get(); }
        set { this.Set(value); }
    }
    internal string Get()
    {
        // Implement UpdatePersonNamePropert here.
        // Maybe convert culture before returning.
        return this.Getter();
    }
    internal void Set(string value)
    {
        // Maybe convert culture before storing.
        this.Setter(value);
    }
}

可以这样调用:

LastName = new PersonNamePropertyTextBox(PropertyBinding.To(Model, Model.GetPersonName().LastName, PeopleResources.LastName_Label));

请注意Model.GetPersonName().LastName必须返回一个指针类型而不是值类型,否则当Setter被调用时LastName不能被更新。例如:

public sealed class Name
{
    public string Value { get; set; }
}

在这个例子中,PersonName的实现如下,但是你的实现可能会有所不同。

public class PersonName
{
    public Name LastName { get; set; }
    public Name FirstName { get; set; }
}

如果没有所有的类信息和与您使用的一些变量相关的强类型,则很难验证,但我认为这应该可以使您摆脱麻烦。