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

时间:2015-11-11 14:16:23

标签: c# wpf mvvm treeview

我正在尝试使用WPF树视图但是有一些问题可以根据需要获取SelectedItemChanged。我的设置目前是这样的:

一堂课:

(defun clear-shell-buffer ()
  "Clear the contents of the current buffer"
  (interactive)
  (erase-buffer)
  ;;  (insert "/usr/games/fortune -a")
  (comint-send-input)
  )

(put 'erase-buffer 'disabled nil)
(eval-after-load 'shell
  '(define-key shell-mode-map [(\C-z)] 'clear-shell-buffer))

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

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

这给我一个很好的树视图,如下所示:

<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

如果用户选择“Name”,这样可以正常工作,但如果他们点击DataSet当然会失败,因为它无法将字符串转换为TestCase。

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

  • 制作它以便您无法选择名称(只需展开它),这可能吗?
  • 当您选择DataSet时,我希望使用所选DataSet的名称获取“父”TestCase togheter。是否有可能以某种方式操作命令参数来获取此信息?

我想通过做一些手动检查后面的代码应该很容易做到但是mvvm怎么样呢?

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

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

1 个答案:

答案 0 :(得分:0)

假设你的命令是用你提到的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没有父元素。

该方法是in this SO Question

您可以获取所选的父级,并使用父元素激活命令。我会在代码背后做这个,但我没有经验。

我不会禁用名称的选择,因为通过上面的解决方案,您可以处理您不想要的情况。此外,用户感觉被禁用的名称是一个错误..

希望有所帮助