RadioButtons通过Command绑定块更改属性

时间:2015-11-07 08:06:21

标签: c# wpf xaml

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

<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:

[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
}

3 个答案:

答案 0 :(得分:0)

使用radiobutton列表,它必须比使用转换器更简单,你可以做你想要的。看这个answer

答案 1 :(得分:0)

我根据您发布的代码创建了以下应用程序,它运行正常。按F1键将TextBlock的文本更改为State1。 您可以按原样使用代码。

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

<强> MainWindow.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);
        }
    }
}

答案 2 :(得分:0)

错误发生在EnumToBooleanCoverter.ConvertBack()。

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; }
}

New EnumToBolleanConverter

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;
    }
}

和XAML

<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"/>