WPF 绑定不适用于嵌套列表视图

WPF Binding not working on nested listview

我有一个带有下拉按钮的树视图。下拉按钮显示用于向树中添加节点的选项。当用户选择一个选项时,我希望命令被触发并由父用户控件中的命令处理。仅供参考,使用 catel MVVM 框架。

XAML

<Grid Margin="10">
  <TreeView x:Name="CriteriaTreeView" ItemsSource="{Binding Criteria}">
    <i:Interaction.Triggers>
      <i:EventTrigger EventName="SelectedItemChanged">
        <catel:EventToCommand Command="{Binding NodeSelectionChanged}" CommandParameter="{Binding ElementName=CriteriaTreeView, Path=SelectedItem}" DisableAssociatedObjectOnCannotExecute="False" />
      </i:EventTrigger>
    </i:Interaction.Triggers>
    <TreeView.Resources>
      <HierarchicalDataTemplate DataType="{x:Type self:Group}" ItemsSource="{Binding Items}">
        <StackPanel Orientation="Horizontal">
          <ComboBox ItemsSource="{Binding OperatorOptions}" SelectedValue="{Binding SelectedOperator}" DisplayMemberPath="DisplayText" SelectedValuePath="Value" />
        </StackPanel>
      </HierarchicalDataTemplate>
      <DataTemplate DataType="{x:Type self:Leaf}">
        <StackPanel Orientation="Horizontal">
          <TextBlock Text="Where Account Number " />
          <ComboBox ItemsSource="{Binding OperatorOptions}" SelectedValue="{Binding SelectedOperator}" DisplayMemberPath="DisplayText" SelectedValuePath="Value" />
          <TextBox Text="{Binding Value}" Width="50" />
        </StackPanel>
      </DataTemplate>
      <DataTemplate DataType="{x:Type self:NodeFactory}">
        <xctk:DropDownButton Content="Add Condition" IsOpen="{Binding IsOpen}">
          <xctk:DropDownButton.DropDownContent>
            <ListView ItemsSource="{Binding AddOptions}" SelectedValue="{Binding SelectedOption}">
              <i:Interaction.Triggers>
                <i:EventTrigger EventName="PreviewMouseLeftButtonDown">
                  <catel:EventToCommand Command="{Binding Source={x:Reference ManageSyncControl}, Path=DataContext.AddNode}" DisableAssociatedObjectOnCannotExecute="False" />
                </i:EventTrigger>
              </i:Interaction.Triggers>
              <ListView.ItemTemplate>
                <DataTemplate>
                  <WrapPanel>
                    <TextBlock Text="{Binding DisplayText}" />
                  </WrapPanel>
                </DataTemplate>
              </ListView.ItemTemplate>
            </ListView>
          </xctk:DropDownButton.DropDownContent>
        </xctk:DropDownButton>
      </DataTemplate>
    </TreeView.Resources>
  </TreeView>
</Grid>

视图模型

    public class ManageSyncedAccountsViewModel: ViewModelEventBase {
      public ManageSyncedAccountsViewModel(IEventAggregator eventAggregator): base(eventAggregator) {
        AddNode = new Command(OnAddNode);
        NodeSelectionChanged = new Command < Node > (OnNodeSelectionChanged);

        var root = new Group("Root");
        var g1 = new Group("Group 1");
        g1.AddNode(new Leaf("Leaf 1"));
        g1.AddNode(new Leaf("Leaf 2"));
        var g2 = new Group("Group2");
        g2.AddNode(new Leaf("Leaf 3"));
        g2.AddNode(new Leaf("Leaf 4"));
        root.AddNode(g1);
        root.AddNode(g2);
        root.AddNode(new Leaf("Leaf 5"));

        Criteria = new List < Group > {
          root
        };
      }

      private void OnNodeSelectionChanged(Node target) {
        SelectedNode = target;
      }

      private void OnAddNode() {
        Console.Out.WriteLine("WOOHOO");
      }

      public List < Group > Criteria {
        get {
          return GetValue < List < Group >> (CriteriaProperty);
        }
        set {
          SetValue(CriteriaProperty, value);
        }
      }

      public static readonly PropertyData CriteriaProperty = RegisterProperty(nameof(Criteria), typeof(List < Group > ));


      public Node SelectedNode {
        get {
          return GetValue < Node > (SelectedNodeProperty);
        }
        set {
          SetValue(SelectedNodeProperty, value);
        }
      }

      public static readonly PropertyData SelectedNodeProperty = RegisterProperty(nameof(SelectedNode), typeof(Node));

      public Command AddNode {
        get;
        private set;
      }
      public Command < Node > NodeSelectionChanged {
        get;
        private set;
      }
    }

当我 运行 出现绑定错误时:

System.Windows.Data Error: 40 : BindingExpression path error: 'AddNode' property not found on 'object' ''MainWindowViewModel' (HashCode=-1718218621)'. BindingExpression:Path=DataContext.AddNode; DataItem='ManageSyncedAccountsView' (Name='ManageSyncControl'); target element is 'EventToCommand' (HashCode=6678752); target property is 'Command' (type 'ICommand')

我尝试使用相对源搜索祖先类型和元素名称,但是这两个选项都返回了更令人困惑的错误消息。显然我在这里遗漏了一些东西。

谢谢。

根据您问题中的错误消息,Button 的 DataContext 是 MainWindowViewModel 类型,但拥有 AddNode 命令的 class 称为 ManageSyncedAccountsViewModel

System.Windows.Data Error: 40 : BindingExpression path error: 'AddNode' property not found on 'object' ''MainWindowViewModel' (HashCode=-1718218621)'. BindingExpression:Path=DataContext.AddNode; DataItem='ManageSyncedAccountsView' (Name='ManageSyncControl'); target element is 'EventToCommand' (HashCode=6678752); target property is 'Command' (type 'ICommand')

尝试将 AddNode 放在按钮可以看到的 MainWindowViewModel 上。