【问题标题】:RadioButtons binding block changing property by CommandRadioButtons 绑定块通过命令更改属性
【发布时间】:2016-02-08 09:58:59
【问题描述】:

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

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

【问题讨论】:

  • 如果可以到达的话,在 SomeCommand_Execute 中放置一些断点。
  • @AnjumSKhan 它会给我什么?
  • 它会告诉您您的 SomeCommand_Execute 方法是否正在见证一些执行?如果无法访问,它将如何执行?也请分享您的 Command 类代码。

标签: c# wpf xaml


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    我根据您发布的代码创建了下面的应用程序,它工作正常。按 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);
            }
        }
    }
    

    【讨论】:

    • 我按照你的要求添加了课程。
    • 当我按 F1 时,TextBlock 显示 State1。我已经仔细检查过了。所以代码工作正常。你能解释一下问题吗?
    • SomeProperty = State2。当我按 F1 时,命令将 SomeProperty 更改为 State1 和 RadioButton 绑定将其更改回 State2
    • @Nodon 将模式更改为 OneWayToSource。通过这样做,您在 RadioButton 中的更改将反映在 SomeProperty 中,但反之则不会。假设你选择了 State2 RButton ,然后按 F1,它会显示 State1,反之亦然。
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-10
      • 2013-06-23
      • 2017-06-27
      相关资源
      最近更新 更多