在具有多个对象类型的树视图中处理SelectedItemChanged

本文关键字:视图 处理 SelectedItemChanged 类型 对象 | 更新日期: 2023-09-27 18:21:28

我正在尝试使用WPF树视图,但在获得所需的SelectedItemChanged时遇到了一些问题。我的设置目前是这样的:

A级:

[ImplementPropertyChanged]
public class TestCase
{
   public string Name { get; set; } 
   public ObservableCollection<string> DataSets { get; set; }
}

然后,我在视图模型中创建了一个可观察的集合,其中包含几个测试用例,并将它们绑定到xaml,如下所示:

<TreeView
    x:Name="TestCases"
    ItemsSource="{Binding TestCases}"
    Margin="0, 10, 0, 0">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="SelectedItemChanged">
            <i:InvokeCommandAction Command="{Binding SelectedTestCaseChangedCommand}" CommandParameter="{Binding ElementName=TestCases, Path=SelectedItem}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type testCases:TestCase}" ItemsSource="{Binding DataSets}">
                <TextBlock Text="{Binding Name}" />
        </HierarchicalDataTemplate>
        <DataTemplate DataType="{x:Type system:String}" >
                <TextBlock Text="{Binding}" />
        </DataTemplate>
        </TreeView.Resources>
</TreeView>

这给了我一个很好的树形视图,看起来像这样:

Name 
  - DataSet
  - DataSet 
Name2 
  - DataSet
  - etc

但问题是这部分:

<i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectedItemChanged">
        <i:InvokeCommandAction Command="{Binding SelectedTestCaseChangedCommand}" CommandParameter="{Binding ElementName=TestCases, Path=SelectedItem}" />
    </i:EventTrigger>
</i:Interaction.Triggers>

如果用户选择"名称",这很好,但如果他们单击数据集,当然会失败,因为它无法将字符串转换为TestCase。

所以我想在这里做几件事:

  • 使它不能选择名称(只是展开它),这可能吗
  • 当您选择一个数据集时,我希望获得具有所选数据集名称的"父"TestCase触发器。是否可以通过某种方式操纵命令参数来获得此信息

我想从代码后面通过手动检查应该很容易做到,但像这样的mvvm呢?

更新1我的视图模型中的命令方法:

    [OnCommand("SelectedTestCaseChangedCommand")]
    public void SelectedTestCaseChanged(TestCase testCase)
    {
        currentTestCase = testCase;
        MessengerInstance.Send(new SelectedTestCaseChangedMessage(testCase));
    }

在具有多个对象类型的树视图中处理SelectedItemChanged

假设您的命令是用您提到的RelayCommand实现的,那么命令看起来像这样:

private ICommand _selectedTestCaseChangedCommand;
public ICommand SelectedTestCaseChangedCommand
{
    get
    {
        if (_selectedTestCaseChangedCommand == null)
        {
            _selectedTestCaseChangedCommand = new RelayCommand<object>(SelectedTestCaseChanged);
        }
        return _selectedTestCaseChangedCommand;
    }
}

您可以像以前那样定义SelectedTestCaseChanged方法,但我建议使用参数类型作为object,因为对象可以是一切。然后你只需要检查你的参数/选择的项目是什么。你有两种可能性。is运算符或as强制转换,后面有空检查。

private void SelectedTestCaseChanged(object obj)
{
    if (obj is TestCase)
    {
        var testCase = (TestCase)obj;
        // Work with testCase
    }
    if (obj is string)
    {
        // Do nothing or whatever
    }
    // Another option is
    var testCase = obj as TestCase;
    if (testCase != null)
    {
        //...
    }
}

如果要获得TreeViewItem的父级,则需要向上转到WPF的Visual Tree,因为TreeViewItems没有parent元素。

此SO问题中描述了该方法。

您可以获取选定元素的父元素,并使用父元素激发命令。我会在代码背后做这件事,但我在那里没有经验。


我不会禁用名称的选择,因为有了上面的解决方案,你就可以处理你不想要的情况。此外,用户感觉禁用的Names是一个bug。。

希望它能帮助