2016-12-06 5 views
1

Я ищу возможность заблокировать переключение RadioButton, но все же поймать Click событие. К сожалению, использование Enabled=false или IsHitTestVisible=false свойств предотвращает событие Click.Отложить изменение RadioButton

Чего я хочу достичь:
1. Пользователь нажимает RadioButton.
2. От Click Событие, вызванное каким-то методом с обработчиком, переданным как аргумент, но активным RadioButton пока не изменилось.
3. Когда вызывается обработчик, в зависимости от результата я хочу переключить RadioButton или нет.

+0

Вы хотите принять делегата в качестве параметра, не так ли? И где они (делегаты) сохраняют: в какой-то частной коллекции или в свойстве Tag или в некоторой метаинформации каждого RadioButton? – EgoPingvina

+0

Чтобы быть более точным, я вызываю метод C++ \ CLI, принимая в качестве аргумента делегата. Я даю его как метод аргумента из моего класса C#. –

ответ

1

Я создал для вас простой пример.

Не забудьте взять с NuGet пакет Prism.

Я создаю три RadioButton и установите для них Func<bool> с некоторых ViewModel. После PreviewMouseDown событий, я вызываю текущий делегат, который является Func<bool> от Tag.

ViewModel:

namespace PostponeRadioButtonChange.Model 
{ 
    using System; 
    using System.Collections.Generic; 

    using Microsoft.Practices.Prism.Mvvm; 

    public class MainWindow : BindableBase 
    { 
     private List<Func<bool>> rbHandlers; 

     private string comment; 

     public List<Func<bool>> RbHandlers 
     { 
      get { return this.rbHandlers; } 
      private set { this.SetProperty(ref this.rbHandlers, value); } 
     } 

     public string Comment 
     { 
      get { return this.comment; } 
      set { this.SetProperty(ref this.comment, value); } 
     } 

     public MainWindow() 
     { 
      this.RbHandlers = new List<Func<bool>> 
      { 
       () => 
        { 
         this.Comment = "First RadioButton clicked"; 
         return false; // Here must be your condition for checking 
        }, 
       () => 
        { 
         this.Comment = "Second RadioButton clicked"; 
         return false; 
        }, 
       () => 
        { 
         this.Comment = "Third RadioButton clicked"; 
         return true; // For example, third not checked after click 
        } 
      }; 
     } 
    } 
} 

Содержание View (дизайнер);

<StackPanel> 

    <TextBox Text="{Binding Path=Comment, Mode=OneWay}"/> 

    <RadioButton Content="First" 
       PreviewMouseDown="RadioButtonMouseDown" 
       Tag="{Binding Path=RbHandlers[0], Mode=OneTime}"/> 

    <RadioButton Content="Second" 
       PreviewMouseDown="RadioButtonMouseDown" 
       Tag="{Binding Path=RbHandlers[1], Mode=OneTime}"/> 

    <RadioButton Content="Third" 
       PreviewMouseDown="RadioButtonMouseDown" 
       Tag="{Binding Path=RbHandlers[2], Mode=OneTime}"/> 

</StackPanel> 

View (код-сзади):

namespace PostponeRadioButtonChange 
{ 
    using System; 
    using System.Windows; 
    using System.Windows.Controls; 
    using System.Windows.Input; 

    using VM = PostponeRadioButtonChange.Model; 

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

     private void RadioButtonMouseDown(object sender, MouseButtonEventArgs e) 
     { 
      var rb = (sender as RadioButton); 

      if (rb == null) 
       throw new InvalidCastException("RadioButtonMouseDown only for RadioButton's"); 

      e.Handled = (rb.Tag as Func<bool>)?.Invoke() ?? false; 
     } 
    } 
} 

Это не хорошо для окончательного решения, но как пример должен помочь вам. Вы также можете создать Command в VM вместо обработчика событий.

Я надеюсь, это вам поможет)

+1

Спасибо, это гораздо больше, чем мне нужно, но очень воспитательный, особенно лямбда-массив. Просто изменив мое событие на «PreviewMouseDown» с «Click», а затем с помощью «e.Handled = true» выполнил задание.У меня уже был обработчик, и вся логика была переведена на эти переключатели. –

+0

Я рад, что смог помочь вам) – EgoPingvina

2

Вы должны обрабатывать событие MouseDown на радиокнопле, а затем оно предотвратит туннелирование, чтобы установить переключатель в качестве установленного.

static void OnMouseDown(object sender, MouseButtonEventArgs e) 
{ 
    // if some logic... 
    e.Handled = true; 
} 
+1

Это не сработает. Во-первых, в wpf RadioButton событие click мыши называется MouseDown или PreviewMouseDown. Во-вторых, в этом случае вы должны использовать PreviewMouseDown. В MouseDown e.Handled = true не будет работать. – EgoPingvina

1

Использование привязок можно поместить вызов в инкубаторе, как это:

XAML

<RadioButton Content="radiobutton" IsChecked="{Binding TestRadio, Mode=TwoWay}"/> 

код

private bool _testRadio; 
    public bool TestRadio 
    { 
     get { return _testRadio; } 
     set { value = testradiohandler(); SetProperty(ref _testRadio, value); } 
    } 
    private bool testradiohandler() 
    { 
     return new Random().NextDouble() >= 0.5; 
    }