diff --git a/src/Shared/HandyControl_Shared/Controls/Block/ToggleBlock.cs b/src/Shared/HandyControl_Shared/Controls/Block/ToggleBlock.cs index 806a156a..5c4102af 100644 --- a/src/Shared/HandyControl_Shared/Controls/Block/ToggleBlock.cs +++ b/src/Shared/HandyControl_Shared/Controls/Block/ToggleBlock.cs @@ -1,9 +1,11 @@ using System.ComponentModel; +using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Markup; using HandyControl.Data; +using HandyControl.Input; using HandyControl.Interactivity; namespace HandyControl.Controls; @@ -19,8 +21,6 @@ public class ToggleBlock : Control public static readonly DependencyProperty IndeterminateContentProperty = DependencyProperty.Register(nameof(IndeterminateContent), typeof(object), typeof(ToggleBlock), new PropertyMetadata(default(object))); public static readonly DependencyProperty ToggleGestureProperty = DependencyProperty.Register(nameof(ToggleGesture), typeof(MouseGesture), typeof(ToggleBlock), new UIPropertyMetadata(new MouseGesture(MouseAction.None), OnToggleGestureChanged)); - private MouseBinding _toggleBinding; - [Category("Appearance")] [TypeConverter(typeof(NullableBoolConverter))] [Localizability(LocalizationCategory.None, Readability = Readability.Unreadable)] @@ -75,9 +75,12 @@ public class ToggleBlock : Control private void OnToggleGestureChanged(MouseGesture newValue) { - InputBindings.Remove(_toggleBinding); - _toggleBinding = new MouseBinding(ControlCommands.Toggle, newValue); - InputBindings.Add(_toggleBinding); + foreach (var binding in InputBindings.OfType().ToList()) + { + InputBindings.Remove(binding); + } + + InputBindings.Add(new SimpleMouseBinding(ControlCommands.Toggle, newValue)); } private void OnToggled(object sender, ExecutedRoutedEventArgs e) diff --git a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems index 8fe51b1f..0caf6682 100644 --- a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems +++ b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems @@ -99,6 +99,7 @@ + diff --git a/src/Shared/HandyControl_Shared/Input/InternalMouseBinding.cs b/src/Shared/HandyControl_Shared/Input/InternalMouseBinding.cs new file mode 100644 index 00000000..03656748 --- /dev/null +++ b/src/Shared/HandyControl_Shared/Input/InternalMouseBinding.cs @@ -0,0 +1,107 @@ +using System; +using System.ComponentModel; +using System.Windows; +using System.Windows.Input; +using System.Windows.Markup; + +namespace HandyControl.Input; + +internal class InternalMouseBinding : InputBinding +{ + public static readonly DependencyProperty MouseActionProperty = DependencyProperty.Register(nameof(MouseAction), + typeof(MouseAction), typeof(MouseBinding), new UIPropertyMetadata(MouseAction.None, new PropertyChangedCallback(OnMouseActionPropertyChanged))); + + private bool _settingGesture = false; + + [TypeConverter(typeof(MouseGestureConverter))] + [ValueSerializer(typeof(MouseGestureValueSerializer))] + public override InputGesture Gesture + { + get => base.Gesture as MouseGesture; + set + { + if (value is MouseGesture mouseGesture) + { + base.Gesture = mouseGesture; + SynchronizePropertiesFromGesture(mouseGesture); + } + } + } + + public MouseAction MouseAction + { + get => (MouseAction) GetValue(MouseActionProperty); + set => SetValue(MouseActionProperty, value); + } + + public InternalMouseBinding() + { + } + + internal InternalMouseBinding(ICommand command, MouseAction mouseAction) : this(command, new MouseGesture(mouseAction)) + { + } + + public InternalMouseBinding(ICommand command, MouseGesture gesture) : base(command, gesture) + { + SynchronizePropertiesFromGesture(gesture); + } + + private static void OnMouseActionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ((InternalMouseBinding) d).SynchronizeGestureFromProperties((MouseAction) e.NewValue); + } + + protected override Freezable CreateInstanceCore() + { + return new InternalMouseBinding(); + } + + private void SynchronizePropertiesFromGesture(MouseGesture mouseGesture) + { + if (!_settingGesture) + { + _settingGesture = true; + try + { + MouseAction = mouseGesture.MouseAction; + } + finally + { + _settingGesture = false; + } + } + } + + private void SynchronizeGestureFromProperties(MouseAction mouseAction) + { + if (!_settingGesture) + { + _settingGesture = true; + try + { + if (Gesture == null) + { + Gesture = new MouseGesture(mouseAction); + } + else + { + ((MouseGesture) Gesture).MouseAction = mouseAction; + } + } + finally + { + _settingGesture = false; + } + } + } + + private void OnMouseGesturePropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (string.Compare(e.PropertyName, "MouseAction", StringComparison.Ordinal) == 0 && + Gesture is MouseGesture mouseGesture) + { + SynchronizePropertiesFromGesture(mouseGesture); + } + } +} diff --git a/src/Shared/HandyControl_Shared/Input/SimpleMouseBinding.cs b/src/Shared/HandyControl_Shared/Input/SimpleMouseBinding.cs new file mode 100644 index 00000000..027ce8bd --- /dev/null +++ b/src/Shared/HandyControl_Shared/Input/SimpleMouseBinding.cs @@ -0,0 +1,105 @@ +using System.ComponentModel; +using System.Windows; +using System.Windows.Input; +using System.Windows.Markup; + +namespace HandyControl.Input; + +internal sealed class SimpleMouseBinding : InputBinding +{ + public static readonly DependencyProperty MouseActionProperty = DependencyProperty.Register(nameof(MouseAction), + typeof(MouseAction), typeof(MouseBinding), new UIPropertyMetadata(MouseAction.None, OnMouseActionPropertyChanged)); + + private bool _settingGesture; + + [TypeConverter(typeof(MouseGestureConverter))] + [ValueSerializer(typeof(MouseGestureValueSerializer))] + public override InputGesture Gesture + { + get => base.Gesture as MouseGesture; + set + { + if (value is not MouseGesture mouseGesture) + { + return; + } + + base.Gesture = mouseGesture; + SynchronizePropertiesFromGesture(mouseGesture); + } + } + + public MouseAction MouseAction + { + get => (MouseAction) GetValue(MouseActionProperty); + set => SetValue(MouseActionProperty, value); + } + + public SimpleMouseBinding() + { + } + + internal SimpleMouseBinding(ICommand command, MouseAction mouseAction) : this(command, new MouseGesture(mouseAction)) + { + } + + public SimpleMouseBinding(ICommand command, MouseGesture gesture) : base(command, gesture) + { + SynchronizePropertiesFromGesture(gesture); + } + + private static void OnMouseActionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ((SimpleMouseBinding) d).SynchronizeGestureFromProperties((MouseAction) e.NewValue); + } + + protected override Freezable CreateInstanceCore() + { + return new SimpleMouseBinding(); + } + + private void SynchronizePropertiesFromGesture(MouseGesture mouseGesture) + { + if (_settingGesture) + { + return; + } + + _settingGesture = true; + + try + { + MouseAction = mouseGesture.MouseAction; + } + finally + { + _settingGesture = false; + } + } + + private void SynchronizeGestureFromProperties(MouseAction mouseAction) + { + if (_settingGesture) + { + return; + } + + _settingGesture = true; + + try + { + if (Gesture is null) + { + Gesture = new MouseGesture(mouseAction); + } + else + { + ((MouseGesture) Gesture).MouseAction = mouseAction; + } + } + finally + { + _settingGesture = false; + } + } +}