【问题标题】:IValueConverter parameter checkIValueConverter 参数检查
【发布时间】:2018-09-24 17:57:43
【问题描述】:

我正在使用 IValueConverter 设置一个复选框。 但我有三个复选框,我像 RadioButton 一样使用。当一个被选中时,另一个需要被取消选中。

所以我做了类似的事情>

<MenuItem StaysOpenOnClick="True" 
          Header="Reiniciar áudio"
          IsCheckable="True"
          Name="RestartAudioCheck" 
          IsChecked="{Binding PlayType, 
          Mode=TwoWay,
          Converter={StaticResource PlayTypeCheckedConverter},
          ConverterParameter=restart}">
</MenuItem>
<MenuItem StaysOpenOnClick="True" 
          Header="Parar áudio"
          IsCheckable="True"
          Name="StopAudioCheck"
          IsChecked="{Binding PlayType, 
            Mode=TwoWay,
          Converter={StaticResource PlayTypeCheckedConverter},
          ConverterParameter=stop}">
</MenuItem>
<MenuItem StaysOpenOnClick="True" 
          Header="Pausar áudio"
          IsCheckable="True"
          Name="PauseAudioCheck"
          IsChecked="{Binding PlayType, 
            Mode=TwoWay,
          Converter={StaticResource PlayTypeCheckedConverter},
          ConverterParameter=pause}">
</MenuItem>

和转换器:

class PlayTypeCheckedConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (!(value is PlayType type))
            return false;

        if (!(parameter is string check))
            return false;

        if (check.CompareTo("restart") == 0 && type == PlayType.Restart)
            return true;
        if (check.CompareTo("stop") == 0 && type == PlayType.Stop)
            return true;
        if (check.CompareTo("pause") == 0 && type == PlayType.Pause)
            return true;

        return false;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (!(value is bool isChecked))
            return true;

        if (!(parameter is string type))
            return PlayType.Restart;

        if (type.CompareTo("restart") == 0 && isChecked)
            return PlayType.Restart;
        if (type.CompareTo("stop") == 0 && isChecked)
            return PlayType.Stop;
        if (type.CompareTo("pause") == 0 && isChecked)
            return PlayType.Pause;

        return PlayType.Restart;
    }
}

我的问题是:以绝对文本之类的 ConverterParameter 作为示例来了解转换器的某些内容是错误的吗? 就像我做的一样,效果很好。

【问题讨论】:

  • 你为什么使用 IvalueCONverter,只需将 3 个复选框与 3 个不同的值绑定,然后在代码后面或视图模型中使用。你可以使用鼠标按下事件。或者我误解了什么......?
  • 每个复选框我没有 3 个不同的值。因此,当 Pause Type = Restart 时,其他复选框将自动取消选中,我将 ValueConverter 设置为 3 复选框
  • 你为什么不直接使用 RadioButton 呢?

标签: c# wpf mvvm


【解决方案1】:

任何属性类型都可以有一个等式转换器。使用它的技巧是传递特定类型的参数,而不是字符串表示。

转换器:

public class EqualityCheckConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return Equals(value, parameter);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (Equals(value, true))
            return parameter;

        return Binding.DoNothing;
    }
}

enum 的示例:

// property to bind
public DayOfWeek Day { get; set; }

绑定:

<Window.Resources>
    <wpfDemos:EqualityCheckConverter x:Key="EqualCheckedConverter"/>
</Window.Resources>

<Menu>
    <MenuItem StaysOpenOnClick="True" 
              Header="Tuesday"
              IsCheckable="True"
              IsChecked="{Binding Day, 
              Mode=TwoWay,
              Converter={StaticResource EqualCheckedConverter},
              ConverterParameter={x:Static system:DayOfWeek.Tuesday}}"/>

    <MenuItem StaysOpenOnClick="True" 
              Header="Wednesday"
              IsCheckable="True"
              IsChecked="{Binding Day, 
              Mode=TwoWay,
              Converter={StaticResource EqualCheckedConverter},
              ConverterParameter={x:Static system:DayOfWeek.Wednesday}}"/>

    <MenuItem StaysOpenOnClick="True" 
              Header="Thursday"
              IsCheckable="True"
              IsChecked="{Binding Day, 
              Mode=TwoWay,
              Converter={StaticResource EqualCheckedConverter},
              ConverterParameter={x:Static system:DayOfWeek.Thursday}}"/>
</Menu>

int 示例

public int TestNum { get; set; }
<Window.Resources>
    <wpfDemos:EqualityCheckConverter x:Key="EqualCheckedConverter"/>
    <system:Int32 x:Key="Zero">0</system:Int32>
    <system:Int32 x:Key="Ten">10</system:Int32>
</Window.Resources>
<Menu>
    <MenuItem StaysOpenOnClick="True" 
              Header="0"
              IsCheckable="True"
              IsChecked="{Binding TestNum, 
              Mode=TwoWay,
              Converter={StaticResource EqualCheckedConverter},
              ConverterParameter={StaticResource Zero}}"/>

    <MenuItem StaysOpenOnClick="True" 
              Header="10"
              IsCheckable="True"
              IsChecked="{Binding TestNum, 
              Mode=TwoWay,
              Converter={StaticResource EqualCheckedConverter},
              ConverterParameter={StaticResource Ten}}"/>
</Menu>

【讨论】:

  • 这是一个不错的解决方案。我不知道使用枚举的静态参数。我会搜索更多。感谢分享。
【解决方案2】:

像您所做的那样显式比较字符串文字通常被认为是一种不好的做法。 WPF 与否,原因很明显,它容易出现运行时错误并且不存在类型检查。

我能想到两种解决方案:

  1. 最常见的方法是在视图模型中添加三个属性,其中只有 getter,如果状态满足,则基本上返回 true 或 false。然后,您可以在播放状态更改时为所有这三个布尔属性提高属性更改。

从视图模型的这个示例中,您可以将视图中的每个复选框绑定到它们各自的属性(IsPlaying,IsStopped,IsPaused):

    private State _playState;
    public State PlayState
    {
        get { return _playState; }
        set {

            SetProperty(ref _playState, value);
            RaisePropertyChanged(nameof(IsPlaying));
            RaisePropertyChanged(nameof(IsPaused));
            RaisePropertyChanged(nameof(IsStopped));
        }
    }

    public bool IsPlaying
    {
        get { return _playState == State.Playing; }
    }
    public bool IsPaused
    {
        get { return _playState == State.Paused; }
    }
    public bool IsStopped
    {
        get { return _playState == State.Stopped; }
    }
  1. 在 XAML 中为 PlayState 属性上的复选框使用 DataTrigger。然后,您可以检查键入的枚举值而不是字符串文字。

【讨论】:

  • 我会试试的。在我的脑海中,当我编写代码时,我尝试保存代码以重用转换器。谢谢!这是一个很好的解决方案
  • 嘿,@Ladder。我需要为每个复选框调用三个 OnPropertyChanged,对吗?
  • 在支持属性上。用一个例子编辑了我的帖子
  • 和我一模一样。谢谢!还有一个问题:在一个 setter 中调用多个属性是否有问题?我的意思是,这不是一个坏习惯吗?
  • 您对所有四个属性使用相同的支持字段 _playState。没关系
猜你喜欢
  • 2016-09-24
  • 2012-12-24
  • 2016-06-01
  • 2012-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-07
  • 2016-10-02
  • 1970-01-01
相关资源
最近更新 更多