使用ReactiveUI和Windows窗体绑定到多个RadioButtons

时间:2015-12-17 16:06:43

标签: winforms mvvm binding reactiveui

我想使用ReactiveUI将我的viewmodel中的属性绑定到Windows窗体应用程序中的几个RadioButtons(在同一组中)。

我在WPF中找到了几个示例,但没有使用Windows窗体的示例。

编辑: 我想避免在ViewModel属性和单选按钮组之间创建1:1映射。我希望同一组中的所有RadioButtons绑定到单个属性,并且每次选择在组内更改时该属性都会更新值

3 个答案:

答案 0 :(得分:2)

在视图上实施<data> <import type="android.view.View"/> <variable name="user" type="com.example.databinding.User"/> </data> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.firstName}" android:visibility="@{user.isFriend ? View.VISIBLE : View.GONE}" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Click Me" android:id="@+id/button" android:layout_gravity="left" android:onClick="@{onClickFriend}"/>

IViewFor<YourViewModel>

应该有用。

答案 1 :(得分:0)

我在开始学习ReactiveUI时发现了这个问题。

我同意将一组单选按钮绑定到单个属性时更可取用于控制基础标量变量。 RadioButtonGroup控件可能是一个非常好的&#34;解决方案,但让我觉得需要相当多的工作。作为一个更简单的解决方案,我编写了一个帮助器类,可以使用或多或少的声明性代码进行设置:

namespace ReactiveUIHelpers
{
  using System;
  using System.Collections.Generic;
  using System.Windows.Forms;

  public class RadioButtonHelper<TValue> where TValue : struct
  {
    private RadioButton defaultRadioButton;
    private Dictionary<RadioButton, TValue> radioButtonValues;
    private Dictionary<TValue, RadioButton> valueRadioButtons;
    private Action<TValue> setter;

    public RadioButtonHelper()
    {
      this.defaultRadioButton = null;
      this.radioButtonValues = new Dictionary<RadioButton, TValue>();
      this.valueRadioButtons = new Dictionary<TValue, RadioButton>();
    }

    public void Register(RadioButton radioButton, TValue value)
    {
      if (this.setter != null)
      {
        throw new ApplicationException($"{nameof(this.Register)} must not be called after {nameof(this.Bind)}!");
      }

      this.defaultRadioButton = this.defaultRadioButton ?? radioButton;
      this.radioButtonValues.Add(radioButton, value);
      this.valueRadioButtons.Add(value, radioButton);
      radioButton.CheckedChanged += this.RadioButton_CheckedChanged;
    }

    public void Bind(IObservable<TValue> observable, Action<TValue> setter)
    {
      if (observable == null)
      {
        throw new ArgumentNullException(nameof(observable));
      }

      if (setter == null)
      {
        throw new ArgumentNullException(nameof(setter));
      }

      this.setter = setter;
      observable.Subscribe(value => this.ValueChanged(value));
    }

    private void ValueChanged(TValue value)
    {
      RadioButton radioButton;
      if (this.valueRadioButtons.TryGetValue(value, out radioButton))
      {
        radioButton.Checked = true;
      }
      else
      {
        this.defaultRadioButton.Checked = true;
      }
    }

    private void RadioButton_CheckedChanged(object sender, EventArgs e)
    {
      RadioButton radioButton = sender as RadioButton;
      if (radioButton == null)
      {
        return;
      }

      if (!radioButton.Checked)
      {
        return;
      }

      TValue value;
      if (this.radioButtonValues.TryGetValue(radioButton, out value))
      {
        if (this.setter == null)
        {
          throw new ApplicationException($"{nameof(this.Bind)} has not been called!");
        }

        this.setter(value);
      }
    }
  }
}

使用的一个例子是:从Form构造函数中调用/调用它是:

this.loadingQueueStateHelper = new RadioButtonHelper<QueueStates>();
this.loadingQueueStateHelper.Register(this.radioButtonLoadingQueueEmpty, QueueStates.E);
this.loadingQueueStateHelper.Register(this.radioButtonLoadingQueueMedium, QueueStates.M);
this.loadingQueueStateHelper.Register(this.radioButtonLoadingQueueFull, QueueStates.F);
this.loadingQueueStateHelper.Bind(this.WhenAnyValue(view => view.ViewModel.LoadingQueueState),
    value => this.ViewModel.LoadingQueueState = value);

答案 2 :(得分:0)

我有一个三态布尔值绑定到一组单选按钮。这是临时的(并且有点冗长),但它为我解决了这个问题。我在表单构造函数中有以下内容:

this.WhenAnyValue( x => x.ViewModel.SomeBoolean )
    .Subscribe( someBoolean =>
    {
        if ( someBoolean == true )
            Option1.Checked = true;
        else if ( someBoolean == false )
            Option2.Checked = true;
        else
            Option3.Checked = true;
    });

this.WhenAnyValue( x => x.Option1.Checked, x => x.Option2.Checked, x => x.Option3.Checked )
    .Subscribe( values =>
    {
        var option1 = values.Item1;
        var option2 = values.Item2;
        var option3 = values.Item3;

        if ( option1 ) ViewModel.SomeBoolean = true;
        if ( option2 ) ViewModel.SomeBoolean = false;
        if ( option3 ) ViewModel.SomeBoolean = null;
    });