2014-07-15 175 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