如何从视图模型更新视图中的单选按钮

本文关键字:新视图 单选按钮 更新 模型 视图 | 更新日期: 2023-09-27 18:28:10

假设我的视图中有几个单选按钮组合在一起.xaml:

<RadioButton GroupName="Group" Content="Item1" Command="{Binding ChangeRadioSelectionCommand}" CommandParameter="Item1" />
<RadioButton GroupName="Group" Content="Item2" Command="{Binding ChangeRadioSelectionCommand}" CommandParameter="Item2" />
<RadioButton GroupName="Group" Content="Item3" Command="{Binding ChangeRadioSelectionCommand}" CommandParameter="Item3" />

然后在我的viewmodel.cs中,我有一些类似的东西:

public class ViewModel : BindableBase
{
  private string radioSelection = "Item1";
  public string RadioSelection
  {
    get { return this.radioSelection; }
    set { SetProperty(ref this.radioSelection, value); }
  }
  public ViewModel() 
  {
    this.ChangeRadioSelectionCommand = new DelegateCommand<string>(this.OnChangeRadioSelection, this.CanChangeRadioSelection);
  }
  public ICommand ChangeRadioSelectionCommand { get; private set; }
  private void OnChangeRadioSelection(string radioSelection)
  {
    RadioSelection = radioSelection;
  }
  private bool CanChangeRadioSelection(string radioSelection) { return true; }
}

这对于将值从视图获取到视图模型非常有效,但如果视图模型发生了变化,我该如何从视图模型转到视图。为了简单起见,假设我在xaml:中添加了一个按钮

<Button Command="{Binding ResetRadioSelectionCommand}" />

它所要做的就是将无线电选择重置为第一项,因此viewmodel.cs看起来像:

public class ViewModel : BindableBase
{
  private string radioSelection = "Item1";
  public string RadioSelection
  {
    get { return this.radioSelection; }
    set { SetProperty(ref this.radioSelection, value); }
  }
  public ViewModel() 
  {
    this.ChangeRadioSelectionCommand = new DelegateCommand<string>(this.OnChangeRadioSelection, this.CanChangeRadioSelection);
    this.ResetRadioSelectionCommand = new DelegateCommand(this.OnResetRadioSelection, this.CanResetRadioSelection);
  }
  public ICommand ChangeRadioSelectionCommand { get; private set; }
  private void OnChangeRadioSelection(string radioSelection)
  {
    RadioSelection = radioSelection;
  }
  private bool CanChangeRadioSelection(string radioSelection) { return true; }
  public ICommand ResetRadioSelectionCommand { get; private set; }
  private void OnResetRadioSelection()
  {
    RadioSelection = "Item1";
  }
  private bool CanResetRadioSelection() { return true; }
}

这将更改radioSelection,但它不会反映在gui中。有办法做到这一点吗?或者也许只是一种更好的方式来处理一般的单选按钮?

如何从视图模型更新视图中的单选按钮

这完全是错误的方式。ViewModel应该包含一个具有合理名称的合理属性。例如CurrentMode。

第一个解决方案

ViewModel

public enum DisplayMode { Vertical, Horizontal, Diagonal }
private DisplayMode currentMode;
public DisplayMode CurrentMode
{
    get { return currentMode; }
    set { SetProperty(ref currentMode, value); }
}

现在您可以通过IValueConverter:将此属性绑定到RadioButton.IsChecked

<RadioButton GroupName="Group" Content="Vertical" IsChecked="{Binding CurrentMode, Converter={StaticResource enumToBoolConverter}, ConverterParameter=Vertical}" />
<RadioButton GroupName="Group" Content="Horizontal" IsChecked="{Binding CurrentMode, Converter={StaticResource enumToBoolConverter}, ConverterParameter=Horizontal}" />
<RadioButton GroupName="Group" Content="Diagonal" IsChecked="{Binding CurrentMode, Converter={StaticResource enumToBoolConverter}, ConverterParameter=Diagonal}" />

转换器对所有枚举都是通用的。您需要将它添加到您的项目中,并在视图的资源块中声明。

public class EnumBooleanConverter : IValueConverter
{
    #region IValueConverter Members
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string parameterString = parameter as string;
        if (parameterString == null)
            return DependencyProperty.UnsetValue;
        if (Enum.IsDefined(value.GetType(), value) == false)
            return DependencyProperty.UnsetValue;
        object parameterValue = Enum.Parse(value.GetType(), parameterString);
        return parameterValue.Equals(value);
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string parameterString = parameter as string;
        if (parameterString == null)
            return DependencyProperty.UnsetValue;
        return Enum.Parse(targetType, parameterString);
    }
    #endregion
}

这是众多解决方案之一。您可能不希望我们为您的属性枚举,因为主题区域未映射到参数枚举。然后您可以绑定到文本值:

第二个解决方案

ViewModel

private string currentMode;
public string CurrentMode
{
    get { return currentMode; }
    set { SetProperty(ref currentMode, value); }
}

查看

<RadioButton Name="RadioButton1"
                     GroupName="Group"
                     Content="Vertical"
                     IsChecked="{Binding Path=CurrentMode, Converter={StaticResource boolToStringValueConverter}, ConverterParameter=Vertical}" />
        <RadioButton Name="RadioButton2"
                     GroupName="Group"
                     Content="Horizontal"
                     IsChecked="{Binding Path=CurrentMode, Converter={StaticResource boolToStringValueConverter}, ConverterParameter=Horizontal}" />
        <RadioButton Name="RadioButton3"
                     GroupName="Group"
                     Content="Diagonal"
                     IsChecked="{Binding Path=CurrentMode, Converter={StaticResource boolToStringValueConverter}, ConverterParameter=Diagonal}" />

转换器

public class BooleanToStringValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (System.Convert.ToString(value).Equals(System.Convert.ToString(parameter)))
        {
            return true;
        }
        return false;
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (System.Convert.ToBoolean(value))
        {
            return parameter;
        }
        return null;
    }
}

一般原则是在ViewModels中存储主题区域的有意义投影。如果要在ViewModel中保留视图属性的存储副本,那就没有什么意义了。RadioSelection是一个毫无意义的名字,如果没有额外的注释,它就无法与模型相关联。