为什么事件在 WPF/MVVM 应用程序中不触发

本文关键字:应用程序 MVVM 事件 WPF 为什么 | 更新日期: 2023-09-27 17:55:43

>我有以下导航栏,Content数据模板标记如下:

<dxn:NavBarControl Name="SideMenuNavBar" DataContext="{Binding}" IsEnabled="{Binding Enabled}" ItemsSource="{Binding Bars}" HorizontalAlignment="Left"  VerticalAlignment="Stretch" Margin="1">
  <dxn:NavBarControl.Resources>
    <Style TargetType="dxn:NavBarGroup">
      <Setter Property="Header" Value="{Binding DisplayText}"/>
      <Setter Property="Content" Value="{Binding MenuItems}"/>
      <Setter Property="DisplaySource" Value="Content"/>
      <Setter Property="ContentTemplate">
        <Setter.Value>
          <DataTemplate>
            <TreeView ItemsSource="{Binding}">
              <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Path=ChildItems}" DataType="{x:Type common:MenuItemBase}">
                  <TextBlock Text="{Binding ItemText}" HorizontalAlignment="Stretch">
                    <TextBlock.ContextMenu>
                      <ContextMenu DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}">
                        <MenuItem Header="{Binding MenuText}" Click="MenuItem_OnClick" />
                      </ContextMenu>
                    </TextBlock.ContextMenu>
                  </TextBlock>
                </HierarchicalDataTemplate>
              </TreeView.ItemTemplate>
            </TreeView>
          </DataTemplate>
        </Setter.Value>
      </Setter>
    </Style>
  </dxn:NavBarControl.Resources>
  <dxn:NavBarControl.View>
    <dxn:NavigationPaneView GroupDisplayMode="Text" ItemDisplayMode="Text" MaxVisibleGroupCount="12"/>
  </dxn:NavBarControl.View>
</dxn:NavBarControl>

绑定正在工作,因为我的一个菜单项树视图正确显示,但是当我单击(MouseDown事件)时没有任何反应,或者当我双击以下处理程序时,处理程序不执行:

private void Control_OnMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
  var x = sender;
}

我在var x = sender;上的断点永远不会被命中。

注意:我知道我不应该使用事件,而应该使用命令或其他一些不太耦合的代码,但我迫切需要演示当用户单击菜单项时会发生什么,并且在事件之前,我的命令代码也没有触发。这里可能出了什么问题?

为什么事件在 WPF/MVVM 应用程序中不触发

首先:ContextMenu完全在您的控件之外VisualTree因此正常的绑定将根本不起作用,除非您按照此处的说明更改绑定

由于您使用的是事件背后的代码,请尝试以下操作:

<MenuItem Header="{Binding MenuText}" MouseDown="MenuItem_MouseDown" />

private void MenuItem_MouseDown(object sender, MouseButtonEventArgs e)
{
  var x = sender;
}

您应该使用命令绑定,确保绑定到创建命令的同一上下文。

如果<MenuItem Header="{Binding MenuText}" ...>绑定正确,则应在同一上下文中创建中继命令。 然后通过以下方式绑定到点击

<MenuItem Click="{Binding ClickCommand}" ...?

但是,如果您需要快速修复,则可以在导航栏控件中使用PreviewMouseButtonDown/Up,然后检查处理程序中单击了什么?

请参阅:获取我clicked/mousedown的元素的名称

<dxn:NavBarControl PreviewMouseUp="NavBar_PreviewMouseUp" ...>

并在后面的代码中。

private void NavBar_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
    var mouseWasUpOn = e.Source as MenuItem;
    if (mouseWasUpOn != null)
    {
        string header = mouseWasDownOn.Header;
    }
}

但请注意,如果正常的事件处理程序不起作用,这只是一种解决方法。理想情况下,您应该绑定到命令!

我对 WPF 很陌生,对 DevExpress WPF 套件也很陌生,所以我只是从某处的示例中复制了上面的原始代码。然后我心想,为什么要ContextMenu?然后,我右键单击菜单项,出现一个空白的上下文菜单项,并触发了事件。我删除了血腥的上下文菜单,现在我的菜单项正在触发事件,就像我问这个问题时想要的那样。TreeView的新结构如下:

<TreeView.ItemTemplate>
  <HierarchicalDataTemplate ItemsSource="{Binding Path=ChildItems}" DataType="{x:Type menus:MenuItemBase}">
    <MenuItem DataContext="{Binding}" Header="{Binding ItemText}" Click="MenuItem_OnClick" />
  </HierarchicalDataTemplate>
</TreeView.ItemTemplate>

仍在尝试使正确的命令绑定正常工作,但这回答了我关于事件的问题。