2014-07-15 144 views
2

现在ReactiveUI 6.0 has been released,我有一个问题:什么是最好的或最有效的方式来绑定ReactiveObject(s)和Windows窗体(s)。ReactiveUI 6.0和WinForms绑定

这是我到目前为止有:

我的模型

namespace WindowsFormsApplication1 
{ 
    #region 

    using System; 
    using System.Reactive.Linq; 

    using ReactiveUI; 

    #endregion 

    public class ClockModel : ReactiveObject 
    { 
     #region Fields 

     private DateTime currentDateTime; 

     #endregion 

     #region Constructors and Destructors 

     public ClockModel() { Observable.Interval(TimeSpan.FromSeconds(1)).Subscribe(s => this.CurrentDateTime = DateTime.Now); } 

     #endregion 

     #region Public Properties 

     public DateTime CurrentDateTime 
     { 
      get { return currentDateTime; } 
      set { this.RaiseAndSetIfChanged(ref currentDateTime, value); } 
     } 

     #endregion 
    } 
} 

我唯一的形式

using System.Windows.Forms; 

namespace WindowsFormsApplication1 
{ 
    public partial class Form1 : Form 
    { 
     readonly ClockModel model = new ClockModel(); 
     public Form1() 
     { 
      InitializeComponent(); 
      this.label1.DataBindings.Add("Text", model, "CurrentDateTime"); 
     } 
    } 
} 

它的工作,但我不激动不已指通过它们的字符串名称来指向每一侧的属性。有没有更好的方法来实现这一点?

更新1

鉴于this extension

public class NameOf<T> 
{ 
    public static string Property<TProp>(Expression<Func<T, TProp>> expression) 
    { 
     var body = expression.Body as MemberExpression; 
     if (body == null) 
      throw new ArgumentException("'expression' should be a member expression"); 
     return body.Member.Name; 
    } 
} 

这是任何形式比前一个更可取?

this.label1.DataBindings.Add(NameOf<Form1>.Property(e => e.label1.Text), model, NameOf<ClockModel>.Property(p => p.CurrentDateTime)); 

更新2

另一部分:

public static class Extensions 
{ 
    public static string GetPropertyName<T,TProp>(this T obj, Expression<Func<T, TProp>> expression) 
    { 
     var body = expression.Body as MemberExpression; 
     if (body == null) 
      throw new ArgumentException("'expression' should be a member expression"); 
     return body.Member.Name; 
    } 
} 

现在,我可以使用:

this.label1.DataBindings.Add(this.GetPropertyName(e => e.label1.Text), model, model.GetPropertyName(p => p.CurrentDateTime)); 

或本:

this.label2.DataBindings.Add(this.label2.GetPropertyName(e => e.Text), model, model.GetPropertyName(p => p.Ticks)); 

我开始喜欢这个,但其他人怎么看待这三种方法?

从技术上讲,表单成为视图和控制器或演示者,而模型仍然是分开的,并且不知道其消费者。这会是首选方法吗?

更新3

这可能会导致一些较真轻度心脏的攻击...基于保罗·贝茨建议 :

namespace WindowsFormsApplication1 
{ 
    #region 

    using System.Windows.Forms; 

    using ReactiveUI; 

    #endregion 

    public partial class Form1 : Form, IViewFor<ClockModel> 
    { 
     #region Constructors and Destructors 

     public Form1() 
     { 
      InitializeComponent(); 
      this.ViewModel = new ClockModel(); 
      this.Bind(ViewModel, vm => vm.CurrentDateTime, v => v.label1.Text); 
      this.Bind(ViewModel, vm => vm.Ticks, v => v.label2.Text); 
     } 

     #endregion 

     #region Public Properties 

     public ClockModel ViewModel { get; set; } 

     #endregion 

     #region Explicit Interface Properties 

     object IViewFor.ViewModel 
     { 
      get { return ViewModel; } 
      set { ViewModel = value as ClockModel; } 
     } 

     #endregion 
    } 
} 
行为

有趣的变化:之前更新3,时间为以秒显示。我只能推断这是由于第三种方法中使用的默认ReactiveUI转换器。我必须更多地了解它。

public class DateTimeStringConverter : IBindingTypeConverter 
{ 
    public int GetAffinityForObjects(Type fromType, Type toType) { return 1; } 

    public bool TryConvert(object @from, Type toType, object conversionHint, out object result) { 
     result = ((DateTime)@from).ToString("F"); 
     return true; 
    } 
} 

我喜欢这种方法的优雅。

还有其他意见吗?

+0

看起来你可以轻松地创建为一个扩展方法。 –

回答

2

最简单的方法是使用ReactiveUI绑定 - 在表单上实现IViewFor<TViewModel>,然后您将获得几种新方法,如BindOneWayBind

退房https://github.com/reactiveui/ReactiveUI/blob/docs/docs/basics/bindings.md了解更多信息

+0

Paul,谢谢你的回应。有没有任何例子,但如何将转换器与绑定关联?谷歌搜索ReactiveUI conversionHint,但在前三页找不到任何东西。 – Darek

+0

你需要实现'IBindingTypeConverter'并通过'Locator.CurrentMutable.Register'注册它。 –

+0

我明白,那部分。我在寻找的是转换器代码的一个例子,以及它应该如何与视图集成。那部分不清楚。另外,我喜欢WPF方法,其中有Convert和CovertBack。我的想法更清晰。 – Darek