从TreeView检索节点上的绑定对象

时间:2012-09-20 12:02:06

标签: c# .net wpf treeview caliburn.micro

我不是WPF的专家,所以请原谅我,如果我的问题很奇怪。如果有什么不合理的话,我会非常乐意详述。

我有一个树视图,它绑定了一个类的可观察集合。当我的程序启动时,我会读取特定目的地的每个C源代码文件,并将其名称和文件路径存储在上述类中。

enter image description here

这是我的XAML:

<TreeView Name="ProgramTree" ItemsSource="{Binding ProgramItemCollection}" 
                                      cal:Message.Attach="[Event PreviewMouseRightButtonDown] = [Action TestRight($dataContext,$eventArgs)];
                                      [Event PreviewMouseDoubleClick] = [Action NodeDoubleClick($dataContext,$eventArgs)]">

    <TreeView.Resources>
        <!--DataTemplate for Program Nodes (Top) and binds FileItemNodes-->
        <HierarchicalDataTemplate DataType="{x:Type my:ProgramItem}"
                                        ItemsSource="{Binding FileItemCollection}">
            <Border Width="100" BorderBrush="RoyalBlue" 
                                            Background="RoyalBlue"  BorderThickness="1" 
                                            CornerRadius="2" Margin="2" Padding="2" >
                <StackPanel Orientation="Horizontal">
                    <Image Style="{StaticResource IconStyle}" Margin="2" Source="{StaticResource FolderIcon}" />
                    <TextBlock Margin="2" Text="{Binding ProgramName}"
                                                           Foreground="White" FontWeight="Bold"/>
                </StackPanel>
            </Border>
        </HierarchicalDataTemplate>
        <!--DataTemplate for File Nodes (Subnodes of Program Nodes)-->
        <HierarchicalDataTemplate DataType="{x:Type my:FileItem}">
            <Border Width="80"  Background="LightBlue" CornerRadius="2" Margin="1" >
                <StackPanel Orientation="Horizontal">
                    <Image Margin="2" />
                    <TextBlock Margin="2" Text="{Binding NodeName}" />
                </StackPanel>
            </Border>
        </HierarchicalDataTemplate>
    </TreeView.Resources>

代码隐藏:

public class FileItem
{
    public string NodeName { get; set; }
    public string FullName { get; set; }
    public string Extension { get; set; }
}

public class ProgramItem : PropertyChangedBase
{
    private ObservableCollection<FileItem> fileItemCollection;
    ...

我现在要做的是在节点上挂钩双击事件并打开相关文件。

    public void NodeDoubleClick(object sender, MouseButtonEventArgs e)
    {
        TreeViewItem treeViewItem = VisualUpwardSearch(e.OriginalSource as DependencyObject);

        if (treeViewItem != null)
        {
            //Open file
        }
    }

    private static TreeViewItem VisualUpwardSearch(DependencyObject source)
    {
        while (source != null && !(source is TreeViewItem))
            source = VisualTreeHelper.GetParent(source);

        return source as TreeViewItem;
    }

我可以毫无问题地检索双击节点(treeviewitem)。问题是我想从我双击的节点检索FileItem的对象以访问filepath属性。这有可能吗?

2 个答案:

答案 0 :(得分:6)

可以通过解析TreeViewItem的DataContext:

FileItem fileItem = (treeViewItem.DataContext as FileItem);

更优雅的方法是在FileItem类中使用MouseInput Bindings和Command。

在您的Datatemplate for FileItem中:

<StackPanel Orientation="Horizontal">
    <StackPanel.InputBindings>
        <MouseBinding MouseAction="LeftDoubleClick" 
                      Command="{Binding OpenFileCommand}" />
    </StackPanel.InputBindings>
    <Image Margin="2" />
    <TextBlock Margin="2" Text="{Binding NodeName}" />
</StackPanel>

在你的FileItem中:

public class FileItem
{
   public FileItem()
   {
       this.OpenFileCommand 
           = new SimpleCommand(()=> Process.StartNew(this.FullName));
   }

   public string NodeName { get; set; }
   public string FullName { get; set; }
   public string Extension { get; set; }
   public ICommand OpenFileCommand { get; set;}
}

P.S。:如果您不熟悉WPF的命令,那么简单的ICommand的基本实现可能是:

public class SimpleCommand : System.Windows.Input.ICommand
{
    public SimpleCommand(Action action)
    {
        this.Action = action;
    }

    public Action Action { get; set; }

    public bool CanExecute(object parameter)
    {
        return (this.Action != null);
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        if (this.Action != null)
        {
            this.Action();
        }
    }
}

命令对于这样的szenarios更有效。你不需要走视觉树,你根本不需要代码。

答案 1 :(得分:0)

检查DataContext的{​​{1}}属性并尝试将其转换为TreeViewItem类型。

此外,您可以将FileItem的模板定义为简单FileItem,而不是DataTemplate