Как я могу предотвратить преждевременное закрытие всплывающих панелей wpf из-за диалогов и выпадающих списков? - PullRequest
2 голосов
/ 22 июля 2011

У меня есть всплывающая панель (как показано ниже), которая, если отсоединена, должна быть невидимой, когда мышь покидает область панели в целом.

flyout panel

Однако я нене требуется закрытие панели в случае возникновения любого из следующих условий:

1) пользователь открывает ContextMenu

2) пользователь выбирает элемент ComboBox, который находится под панелью (как показано выше)

3) Диалоговое окно подтверждения, которое появляется из-за действий пользователя (таких как удаление элемента в DataGrid)

Операции с контекстным меню легко отслеживать (ContextMenuOpening и ContextMenuClosing событий) для обработки первого случая, но я пока не нашел хороших способов обработки двух других случаев, в частности открытия диалогов отслеживания.

Есть идеи?

Моя всплывающая панель - это просто сетка, видимость и содержание которой определены в коде:

<Grid Name="UndockedGrid" ContextMenuOpening="Grid_ContextMenuOpening" ContextMenuClosing="Grid_ContextMenuClosing" MouseLeave="Grid_MouseLeave">
    <!-- Toolbox (undocked) -->
    <ScrollViewer Name="ToolBoxUndockedViewer">
        <StackPanel Name="ToolBoxUndockedPanel" />
    </ScrollViewer>
</Grid>

1 Ответ

0 голосов
/ 23 июля 2011

Я применил RoutedEvent подход к этой проблеме, поскольку мои модели представлений не обрабатывают диалоговые рабочие процессы непосредственно в этой версии.

Чтобы получить требуемое поведение для комбинированных окон сетки данных, я расширил DataGrid чтобы добавить перенаправленные события, которые я хотел отслеживать:

public class RoutableDataGrid : DataGrid
{
    public static readonly RoutedEvent ElementOpenedEvent = EventManager.RegisterRoutedEvent("ElementOpened", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(RoutableDataGrid));

    public event RoutedEventHandler ElementOpened
    {
        add { AddHandler(ElementOpenedEvent, value); }
        remove { RemoveHandler(ElementOpenedEvent, value); }
    }

    public static readonly RoutedEvent ElementClosedEvent = EventManager.RegisterRoutedEvent("ElementClosed", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(RoutableDataGrid));

    public event RoutedEventHandler ElementClosed
    {
        add { AddHandler(ElementClosedEvent, value); }
        remove { RemoveHandler(ElementClosedEvent, value); }
    }

    public void RaiseElementOpened()
    {
        RaiseEvent(new RoutedEventArgs(RoutableDataGrid.ElementOpenedEvent, this));
    }

    public void RaiseElementClosed()
    {
        RaiseEvent(new RoutedEventArgs(RoutableDataGrid.ElementClosedEvent, this));
    }
}

И DataGridComboBoxColumn был расширен для запуска новых перенаправленных событий:

public class BindableDataGridComboBoxColumn : DataGridComboBoxColumn
{
    protected RoutableDataGrid ParentGrid { get; set; }

    protected FrameworkElement Element { get; set; }

    protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
    {
        Element = base.GenerateEditingElement(cell, dataItem);
        Element.MouseEnter += new System.Windows.Input.MouseEventHandler(element_MouseEnter);
        Element.MouseLeave += new System.Windows.Input.MouseEventHandler(element_MouseLeave);
        CopyItemsSource(Element);
        return Element;
    }

    void element_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
    {
        if (ParentGrid != null)
        {
            ParentGrid.RaiseElementClosed();
        }
    }

    void element_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
    {
        if (ParentGrid != null)
        {
            ParentGrid.RaiseElementOpened();
        }
    }
}

Больше взлома, так какMessageBox - это запечатанный класс, мне пришлось создать класс-оболочку для запуска перенаправленных событий, используя MessageBox (и поместить экземпляр этого элемента в xaml, чтобы он находился в визуальном дереве):

public class RoutedEventPlaceHolder : UIElement
{
    public static readonly RoutedEvent ElementOpenedEvent = EventManager.RegisterRoutedEvent("ElementOpened", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(RoutedEventPlaceHolder));

    public event RoutedEventHandler ElementOpened
    {
        add { AddHandler(ElementOpenedEvent, value); }
        remove { RemoveHandler(ElementOpenedEvent, value); }
    }

    public static readonly RoutedEvent ElementClosedEvent = EventManager.RegisterRoutedEvent("ElementClosed", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(RoutedEventPlaceHolder));

    public event RoutedEventHandler ElementClosed
    {
        add { AddHandler(ElementClosedEvent, value); }
        remove { RemoveHandler(ElementClosedEvent, value); }
    }

    public void RaiseElementOpened()
    {
        RaiseEvent(new RoutedEventArgs(RoutedEventPlaceHolder.ElementOpenedEvent, this));
    }

    public void RaiseElementClosed()
    {
        RaiseEvent(new RoutedEventArgs(RoutedEventPlaceHolder.ElementClosedEvent, this));
    }

    public MessageBoxResult ShowMessageBox(string text, string caption, MessageBoxButton button)
    {
        RaiseElementOpened();
        MessageBoxResult result = MessageBox.Show(text, caption, button);
        RaiseElementClosed();
        return result;
    }
}

Тогда, наконец, я могу подписаться на новые перенаправленные события на всплывающей панели:

        <Grid Name="UndockedGrid" lib:RoutedEventPlaceHolder.ElementOpened="Grid_ElementOpened" lib:RoutableDataGrid.ElementOpened="Grid_ElementOpened" ContextMenuOpening="Grid_ContextMenuOpening" ContextMenuClosing="Grid_ContextMenuClosing" MouseLeave="Grid_MouseLeave">
            <!-- Toolbox (undocked) -->
            <ScrollViewer Grid.Row="0" Grid.Column="0" Name="ToolBoxUndockedViewer" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Visibility="Collapsed" MouseLeave="ToolBoxUndockedViewer_MouseLeave">
                <StackPanel Name="ToolBoxUndockedPanel" MinWidth="200" Background="{StaticResource ControlBackgroundBrush}" />
            </ScrollViewer>
        </Grid>

Это не идеальное решение.Я приму любые другие ответы, которые более элегантны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...