如何在鼠标离开时关闭mahapps datetimepicker弹出窗口并在单击鼠标时不关闭

时间:2020-07-16 21:20:00

标签: wpf popup datetimepicker mahapps.metro

我试图弄清楚如何在鼠标离开时关闭mahapps datetimepicker弹出窗口,而在点击鼠标时不关闭。我已经创建了如下所示的附加行为,它使我获得了99%的收益。

using System;
using System.Reactive.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using MahApps.Metro.Controls;
using Microsoft.Xaml.Behaviors;
using ReactiveUI;

public sealed class CloseDateTimePickerPopUpOnMouseOff : Behavior<DateTimePicker>
{
    //Fields
    private IDisposable _dateTimePickerLoaded;
    private IDisposable _dateTimePickerPopupBorderMouseLeaveSubscription;
    private IDisposable _dateTimePickerPopupBorderMouseEnterSubscription;
    private IDisposable _dateTimePickerPopupComboBoxGridMouseEnterSubscription;
    private IDisposable _dateTimePickerPopupComboBoxGridMouseLeaveSubscription;


    protected override void OnAttached()
    {
        base.OnAttached();

        _dateTimePickerLoaded = Observable
            .FromEventPattern<RoutedEventArgs>(AssociatedObject, nameof(AssociatedObject.Loaded))
            .Take(1)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Select(_ => AssociatedObject.Template)
            .Where(_ => _ != null)
            .Subscribe(controlTemplate =>
            {
                var canClose = true;

                var successfullyRetrievedControlTemplateObjects = true;

                var dateTimePickerPopup = controlTemplate
                    .FindName("PART_Popup", AssociatedObject) as Popup;

                var dateTimePickerPopupBorder = controlTemplate
                    .FindName("PART_PopupContainer", AssociatedObject) as Border;

                var dateTimePickerPopupHourComboBox = controlTemplate
                    .FindName("PART_HourPicker", AssociatedObject) as ComboBox;

                var dateTimePickerPopupMinuteComboBox = controlTemplate
                    .FindName("PART_MinutePicker", AssociatedObject) as ComboBox;

                var dateTimePickerPopupAmPmComboBox = controlTemplate
                    .FindName("PART_AmPmSwitcher", AssociatedObject) as ComboBox;

                var dateTimePickerPopupComboBoxGrid = controlTemplate
                    .FindName("PART_ClockPartSelectorsHolder", AssociatedObject) as Grid;

                if (dateTimePickerPopup == null
                    || dateTimePickerPopupBorder == null
                    || dateTimePickerPopupHourComboBox == null
                    || dateTimePickerPopupMinuteComboBox == null
                    || dateTimePickerPopupComboBoxGrid == null
                    || dateTimePickerPopupAmPmComboBox == null)
                    successfullyRetrievedControlTemplateObjects = false;

                if (!successfullyRetrievedControlTemplateObjects) return;

                _dateTimePickerPopupBorderMouseEnterSubscription =
                    dateTimePickerPopupBorder
                        .Events()
                        .MouseEnter
                        .ObserveOn(RxApp.MainThreadScheduler)
                        .Subscribe(_ => { canClose = true; });

                _dateTimePickerPopupBorderMouseLeaveSubscription =
                    dateTimePickerPopupBorder
                        .Events()
                        .MouseLeave
                        .Where(_ => canClose && dateTimePickerPopupHourComboBox.IsDropDownOpen == false && dateTimePickerPopupMinuteComboBox.IsDropDownOpen == false && dateTimePickerPopupAmPmComboBox.IsDropDownOpen == false)
                        .ObserveOn(RxApp.MainThreadScheduler)
                        .Subscribe(_ =>
                        {
                            dateTimePickerPopup
                                .IsOpen = false;
                        });

                _dateTimePickerPopupComboBoxGridMouseEnterSubscription =
                    dateTimePickerPopupComboBoxGrid
                        .Events()
                        .MouseEnter
                        .ObserveOn(RxApp.MainThreadScheduler)
                        .Subscribe(_ => { canClose = false; });

                _dateTimePickerPopupComboBoxGridMouseLeaveSubscription =
                    dateTimePickerPopupComboBoxGrid
                        .Events()
                        .MouseLeave
                        .ObserveOn(RxApp.MainThreadScheduler)
                        .Subscribe(_ => { canClose = dateTimePickerPopupBorder.IsMouseOver; });
            });
    }

    protected override void OnDetaching()
    {
        _dateTimePickerLoaded?.Dispose();
        _dateTimePickerPopupBorderMouseLeaveSubscription?.Dispose();
        _dateTimePickerPopupComboBoxGridMouseEnterSubscription?.Dispose();
        _dateTimePickerPopupComboBoxGridMouseLeaveSubscription?.Dispose();
        _dateTimePickerPopupBorderMouseEnterSubscription?.Dispose();
        base.OnDetaching();
    }
}

Xaml

<controls:DateTimePicker x:Name="StartDateTimePicker"
                         controls:TextBoxHelper.Watermark="Select a start date"
                         FontSize="9"
                         SelectedDateTime="{Binding StartDtm}">
                            
      <interactivity:Interaction.Behaviors>
           <behaviors:CloseDateTimePickerPopUpOnMouseOff/>
      </interactivity:Interaction.Behaviors>

 </controls:DateTimePicker>

此方法有效,并在使用组合框小时:分钟:上午/下午时使弹出窗口不关闭,并在鼠标离开实际弹出窗口时关闭。我要解决的一个问题是,当我打开这些组合框之一并将其保持打开状态而不选择任何项目时,然后单击日历中的某个日期以关闭弹出窗口。我尝试将弹出窗口设置为StaysOpen = true,但是没有运气。我可以在重新打开弹出窗口的地方添加一些技巧,但随后您会关闭它并重新打开弹出窗口。

0 个答案:

没有答案