Я применил 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>
Это не идеальное решение.Я приму любые другие ответы, которые более элегантны.