C# RadioButtons绑定块通过命令更改属性

C# RadioButtons绑定块通过命令更改属性,c#,wpf,xaml,C#,Wpf,Xaml,我的代码的问题是RadioButton的绑定不允许代理修改属性。委托它更改,然后绑定,它更改为旧值。我需要能够通过命令和RadioButtons更改属性 <Window.InputBindings> <KeyBinding Key="F1" Command="{Binding SomeCommand}"/> </Window.InputBindings> <StackPanel> <TextBlock Text="{Bindi

我的代码的问题是
RadioButton
的绑定不允许代理修改属性。委托它更改,然后绑定,它更改为旧值。我需要能够通过命令和
RadioButton
s更改属性

<Window.InputBindings>
    <KeyBinding Key="F1" Command="{Binding SomeCommand}"/>
</Window.InputBindings>
<StackPanel>
    <TextBlock Text="{Binding Path=SomeProperty}"/>
    <RadioButton IsChecked="{Binding Path=SomeProperty, Mode=TwoWay, Converter={StaticResource ETBConverter}, ConverterParameter=State1}" Content="State1"/>
    <RadioButton IsChecked="{Binding Path=SomeProperty, Mode=TwoWay, Converter={StaticResource ETBConverter}, ConverterParameter=State2}" Content="State2"/>
</StackPanel>

public enum TestEnum
{
    State1,
    State2,
}

public class TestViewModel : BaseViewModel
{
    private TestEnum _someProperty;

    public TestEnum SomeProperty
    {
        get { return _someProperty; }
        set
        {
            if (_someProperty != value)
            {
                _someProperty = value;
                OnPropertyChanged();
            }
        }
    }

    public Command SomeCommand { get; private set; }

    public TestViewModel()
    {
        _someProperty = TestEnum.State2;
        SomeCommand = new Command(SomeCommand_Execute);
    }

    private void SomeCommand_Execute(object obj)
    {
        SomeProperty = SomeProperty == TestEnum.State1 ? TestEnum.State2 : TestEnum.State1;
    }
}

公共枚举测试数
{
国家1,
国家2,
}
公共类TestViewModel:BaseViewModel
{
私有财产;
公共测试属性
{
获取{return\u someProperty;}
设置
{
if(_someProperty!=值)
{
_someProperty=值;
OnPropertyChanged();
}
}
}
公共命令SomeCommand{get;private set;}
公共TestViewModel()
{
_someProperty=TestEnum.State2;
SomeCommand=新命令(SomeCommand\u Execute);
}
私有void SomeCommand_Execute(object obj)
{
SomeProperty=SomeProperty==TestEnum.State1?TestEnum.State2:TestEnum.State1;
}
}
更新1:

[Localizability(LocalizationCategory.NeverLocalize)]
public class EnumToBooleanConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        string parameterString = parameter as string;
        if (parameterString == null)
            return false;

        if (Enum.IsDefined(value.GetType(), value) == false)
            return false;

        object parameterValue = Enum.Parse(value.GetType(), parameterString);

        return parameterValue.Equals(value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        string parameterString = parameter as string;
        if (parameterString == null)
            return DependencyProperty.UnsetValue;

        return Enum.Parse(targetType, parameterString);
    }
}
public abstract class BaseViewModel : NotifyPropertyChanged
{
    protected Dispatcher UIDispatcher;

    public BaseViewModel()
    {
        UIDispatcher = Dispatcher.CurrentDispatcher;
    }

    protected void InvokeInUIThread(Action action)
    {
        if (Thread.CurrentThread == UIDispatcher.Thread)
            action();
        else
            UIDispatcher.InvokeAsync(action, DispatcherPriority.Send);
    }
}
public abstract class NotifyPropertyChanged : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
public class Command : ICommand
{
    #region Fields

    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;

    #endregion // Fields

    #region Constructors

    public Command(Action<object> execute)
        : this(execute, null)
    {
    }

    public Command(Action<object> execute, Predicate<object> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");

        _execute = execute;
        _canExecute = canExecute;
    }
    #endregion // Constructors

    #region ICommand Members

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        _execute(parameter);
    }

    public void OnCanExecutedChanged()
    {
        CommandManager.InvalidateRequerySuggested();
    }

    #endregion // ICommand Members
}
[可本地化性(本地化类别.永不本地化)]
公共类EnumToBooleanConverter:IValueConverter
{
公共对象转换(对象值、类型targetType、对象参数、CultureInfo区域性)
{
string parameterString=作为字符串的参数;
if(parameterString==null)
返回false;
if(Enum.IsDefined(value.GetType(),value)==false)
返回false;
object parameterValue=Enum.Parse(value.GetType(),parameterString);
返回参数value.Equals(值);
}
公共对象转换回(对象值、类型targetType、对象参数、CultureInfo区域性)
{
string parameterString=作为字符串的参数;
if(parameterString==null)
返回dependencProperty.unset值;
返回Enum.Parse(targetType,parameterString);
}
}
公共抽象类BaseViewModel:NotifyPropertyChanged
{
受保护的调度器;
公共BaseViewModel()
{
UIDispatcher=Dispatcher.CurrentDispatcher;
}
受保护的void InvokeInUIThread(操作)
{
if(Thread.CurrentThread==UIDispatcher.Thread)
动作();
其他的
UIDispatcher.InvokeAsync(操作,DispatcherPriority.Send);
}
}
公共抽象类NotifyPropertyChanged:INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
受保护的void OnPropertyChanged([CallerMemberName]字符串propertyName=”“)
{
if(PropertyChanged!=null)
{
PropertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
}
}
公共类命令:ICommand
{
#区域字段
只读操作_执行;
只读谓词_canExecute;
#endregion//字段
#区域构造函数
公共命令(操作执行)
:此(执行,空)
{
}
公共命令(动作执行,谓词canExecute)
{
if(execute==null)
抛出新的ArgumentNullException(“执行”);
_执行=执行;
_canExecute=canExecute;
}
#endregion//构造函数
#区域ICommand成员
公共事件事件处理程序CanExecuteChanged
{
添加{CommandManager.RequerySuggested+=value;}
删除{CommandManager.RequerySuggested-=value;}
}
公共布尔CanExecute(对象参数)
{
返回_canExecute==null?true:_canExecute(参数);
}
public void Execute(对象参数)
{
_执行(参数);
}
OnCanExecutedChanged()上的公共void
{
CommandManager.InvalidateRequestSuggested();
}
#endregion//ICommand成员
}

使用单选按钮列表,它必须比使用转换器更简单,并且您可以做您想做的事情。看看这个

我根据您发布的代码创建了下面的应用程序,它运行良好。按F1键将文本块的文本更改为状态1。 您可以按原样使用代码

注意:我没有使用您的ETBConverter,因为我没有相应的代码。我相信这是一些枚举到布尔的转换器。你可以看到我的代码,如果这不能解决你的问题。告诉我你的ETB转换,我会照顾它的。另外,我没有BaseViewModel代码,所以我实现了INotifyPropertyChanged接口

main window.xaml

<Window x:Class="WpfCommands.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.InputBindings>
        <KeyBinding Key="F1" Command="{Binding SomeCommand}"/>
    </Window.InputBindings>
    <Window.Resources>

    </Window.Resources>
    <StackPanel>
        <TextBlock Text="{Binding Path=SomeProperty}"/>
        <RadioButton IsChecked="{Binding Path=SomeProperty, Mode=TwoWay}" Content="State1"/>
        <RadioButton IsChecked="{Binding Path=SomeProperty, Mode=TwoWay}" Content="State2"/>
    </StackPanel>
</Window>

MainWindow.xaml.cs

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace WpfCommands
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new TestViewModel();
        }
    }

    public enum TestEnum
    {
        State1,
        State2,
    }

    public class TestViewModel : INotifyPropertyChanged
    {
        private TestEnum _someProperty;

        public TestEnum SomeProperty
        {
            get { return _someProperty; }
            set
            {
                if (_someProperty != value)
                {
                    _someProperty = value;
                    OnPropertyChanged("SomeProperty");
                }
            }
        }

        public Command SomeCommand { get; private set; }

        public TestViewModel()
        {
            _someProperty = TestEnum.State2;
            SomeCommand = new Command(SomeCommand_Execute);
        }

        private void SomeCommand_Execute(object obj)
        {
            SomeProperty = SomeProperty == TestEnum.State1 ? TestEnum.State2 : TestEnum.State1;
            System.Diagnostics.Debug.WriteLine("------------- executed ---------------");
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string propname)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propname));
        }
    }

    public class Command : ICommand
    {
        public delegate void CommandExecuteHandler(object obj);
        CommandExecuteHandler handler;

        public Command(CommandExecuteHandler callback)
        {
            handler = callback;
        }

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {
            handler(parameter);
        }
    }
}
使用系统;
使用系统组件模型;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Input;
命名空间WpfCommands
{
/// 
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
this.DataContext=newtestviewmodel();
}
}
公共枚举测试数
{
国家1,
国家2,
}
公共类TestViewModel:INotifyPropertyChanged
{
私有财产;
公共测试属性
{
获取{return\u someProperty;}
设置
{
if(_someProperty!=值)
{
_someProperty=值;
OnPropertyChanged(“SomeProperty”);
}
}
}
公共命令SomeCommand{get;private set;}
公共TestViewModel()
{
_someProperty=TestEnum.State2;
SomeCommand=新命令(SomeCommand\u Execute);
}
私有void SomeCommand_Execute(object obj)
{
SomeProperty=SomeProperty==TestEnum.State1?TestEnum.State2:TestEnum.State1;
System.Diagnostics.Debug.WriteLine(“--------------已执行-----------------”;
}
聚氨基甲酸酯
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
    if ((bool)value)
    {
        string parameterString = parameter as string;
        if (parameterString == null)
            return DependencyProperty.UnsetValue;

        return Enum.Parse(targetType, parameterString);
    }
    else
        return DependencyProperty.UnsetValue;
}
public class TestEnumExtension : TypedValueExtension<TestEnum>
{
    public TestEnumExtension(TestEnum value) : base(value) { }
}

public class TypedValueExtension<T> : MarkupExtension
{
    public TypedValueExtension(T value) { Value = value; }
    public T Value { get; set; }
    public override object ProvideValue(IServiceProvider sp) { return Value; }
}
public class EnumToBooleanConverter : IValueConverter
{
    public object Convert(
        object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (TestEnum)value == (TestEnum)parameter;
    }

    public object ConvertBack(
        object value, Type targetType, object parameter, CultureInfo culture)
    {
        if ((bool)value)
            return parameter;
        else
            return DependencyProperty.UnsetValue;
    }
}
<RadioButton IsChecked="{Binding Path=SomeProperty, Mode=TwoWay, 
    Converter={StaticResource ETBConverter}, ConverterParameter={exten:TestEnum State1}}"
             Content="State1"/>
<RadioButton IsChecked="{Binding Path=SomeProperty, Mode=TwoWay, 
    Converter={StaticResource ETBConverter}, ConverterParameter={exten:TestEnum State2}}"
             Content="State2"/>