2

フライアウト パネルがあります (以下の図を参照)。ドッキングを解除すると、通常、マウスがパネル領域から離れたときに非表示になります。

フライアウト パネル

ただし、次のいずれかの条件が発生した場合にパネルを閉じたくありません。

1) ユーザーがContextMenu

2) ユーザーがComboBoxパネルの下にあるアイテムを選択する (上図のように)

DataGrid3) ユーザーの操作 ( 内のアイテムの削除など)によって表示される確認ダイアログ

コンテキスト メニュー操作 (ContextMenuOpeningおよびContextMenuClosingイベント) を追跡して最初のケースを処理するのは簡単ですが、他の 2 つのケース、特に開いているダイアログを追跡する良い方法はまだ見つかりません。

何か案は?

私のフライアウト パネルは、可視性とコンテンツがコード ビハインドで決定される単なるグリッドです。

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

1 に答える 1

0

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>

これは理想的な解決策ではありません。よりエレガントな他の答えを受け入れます。

于 2011-07-23T05:51:48.097 に答える