4

私はWPFの専門家ではないので、質問の言い回しがおかしい場合はご容赦ください。何か意味がわからない場合は、詳しく説明させていただきます。

クラスのobservablecollectionをバインドするツリービューがあります。プログラムが起動すると、特定の宛先にあるすべてのCソースコードファイルを読み取り、その名前とファイルパスを上記のクラスに保存します。

ここに画像の説明を入力してください

これが私の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のオブジェクトを取得したいということです。これは可能ですか?

4

2 に答える 2

8

TreeViewItemのDataContextを解決することで可能になります。

FileItem fileItem = (treeViewItem.DataContext as FileItem);

より洗練された方法は、FileItemクラスでMouseInputBindingsとCommandを使用することです。

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;}
}

PS: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();
        }
    }
}

このようなシナリオでは、コマンドの方がはるかに効果的です。ビジュアルツリーを歩く必要はなく、コードビハインドもまったく必要ありません。

于 2012-09-20T12:29:06.103 に答える
1

DataContextのプロパティを確認し、型TreeViewItemにキャストしてみてくださいFileItem

また、FileItemのテンプレートをDataTemplate、ではなく単純なものとして定義することもできますHierarchicalDataTemplate

于 2012-09-20T12:23:59.237 に答える