2015-11-07 83 views
0

我的代码的问题是RadioButton的绑定,并且不允许委托修改属性。委托它更改并绑定,它将更改为旧值。我需要能够通过命令和RadioButton s来改变财产。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 
} 
+0

把一些断点SomeCommand_Execute如果可达。 – AnjumSKhan

+0

@AnjumSKhan它会给我什么? – Nodon

+0

它会告诉你,如果你的SomeCommand_Execute方法正在见证一些执行或没有?如果它无法实现将如何执行?也请分享你的Command类代码。 – AnjumSKhan

回答

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

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

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

0

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

注:我没有使用您的ETBConverter,因为我没有代码。我相信这是一些枚举到布尔转换器。你可以看到我的代码,如果这不能解决你的问题。告诉我你的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); 
     } 
    } 
} 
+0

我添加了你所要求的类。 – Nodon

+0

你的代码有同样的问题。 – Nodon

+0

当我按F1时,TextBlock显示State1。我仔细检查过。所以代码工作正常。你能解释更多的问题吗? – AnjumSKhan