我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
是一个密封类,我必须构建一个包装类来使用 a 触发路由事件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>
这不是一个理想的解决方案。我会接受任何其他更优雅的答案。