2011-09-23 100 views
3

对于涉及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; } 

什么,我会真的像现在是能够做的仅仅是通过在当前属性,即“姓”和标签值,并让迷你视图模型设置相应的getter/setter的代表,是这样的:

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

我奋力至于如何做到这一点,虽然。有任何想法吗?

扩展(处理更新PERSONNAME在Model)

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; 
    } 
} 
+0

为什么你想避免反思? – CodesInChaos

+2

@CodeInChaos:有趣的问题,我尽量避免反射,大致像交通堵塞。我不喜欢在繁忙的交通中开车,但有时你只需... –

+1

@CodeInChaos,所有的事情都是平等的 - 即如果你可以在没有反思的情况下同样好地解决问题 - 不使用的解决方案反射更好,因为它更安全。 –

回答

1

某些属性尝试实现粘合剂类来管理绑定。在这种情况下,我使用了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必须返回一个指针类型不是值类型,否则当二传手叫名字不能被更新。例如:

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

在此示例中,PersonName实现如下,但实现可能不同。

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

    public Name FirstName { get; set; } 
} 

没有一些你以前这是很难验证,但我认为这应该让你摆脱困境的变量相关的所有分类信息和强大的类型。

希望这会有所帮助。

+0

嗨,伯尼,这正是我要求的主要内容,但我并没有对它进行研究。例如,Model.GetPersonName()。LastName将不会编译为请求的Name参数的arg。名称应该是一个新的未包装的包装? PropertyBinding只是你构造的一个类,还是它与框架中的某些东西有关(动态?)。我错过了什么? – Berryl

+0

啊,是的,我看到了问题。你能发布GetPersonName()和PersonName类型吗?理想情况下,您将通过一个接口来实现PersonName上的Get/Set函数,这是我过去如何完成的。 PropertyBinding只是一个自定义类。 –

+0

查看我的更新,了解我如何实现PersonName模型,但不知道它是完全实现的。 –

相关问题