2015-11-07 141 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