Filip Filipovic
Filip Filipovic

Reputation: 149

WPF TreeView binding command and passing which element was clicked on

How to bind command to element in TreeView. I have MainWindowViewModel with TreeViewCommand and I tried to add button around element but command didn't wont to be called. Is there any other way to call command and pass which element was clicked on?

<TreeView x:Name="MainTreeView" HorizontalAlignment="Stretch" Margin="10" VerticalAlignment="Stretch" ItemsSource="{Binding Departments}">
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding Positions}" DataType="{x:Type VM:Department}">
                <Button Command="{Binding TreeViewCommand}" CommandParameter="{Binding DepartmentName}" BorderThickness="0" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" >
                    <Label Content="{Binding DepartmentName}"/>
                </Button>
                <HierarchicalDataTemplate.ItemTemplate>
                    <HierarchicalDataTemplate ItemsSource="{Binding Employees}" DataType="{x:Type VM:Position}">
                        <Button BorderThickness="0" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" >
                        <Label Content="{Binding PositionName}"/>
                        </Button>
                        <HierarchicalDataTemplate.ItemTemplate>
                            <DataTemplate DataType="{x:Type VM:Employee}">
                                <Button BorderThickness="0" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" >
                                <Label Content="{Binding EmployeeName}"/>
                                </Button>
                            </DataTemplate>
                        </HierarchicalDataTemplate.ItemTemplate>
                    </HierarchicalDataTemplate>
                </HierarchicalDataTemplate.ItemTemplate>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>

My MainWindowViewMode is

public class MainWindowViewModel : ViewModelBase
{

    private List<Department> departments;
    public MyICommand<string> TreeViewCommand { get; private set; }

    public MainWindowViewModel()
    {
        TreeViewCommand = new MyICommand<string>(myTreeViewCommand);
        Departments = new List<Department>()
        {
            new Department("DotNet"),
            new Department("PHP")
        };
    }

    public List<Department> Departments
    {
        get
        {
            return departments;
        }
        set
        {
            departments = value;
            OnPropertyChanged("Departments");
        }
    }

    public void myTreeViewCommand(string par) 
    {
        Console.ReadKey();
    }
}

Upvotes: 2

Views: 922

Answers (1)

Gleb
Gleb

Reputation: 1761

As your TreeViewCommand is inside your TreeView scope it has the Departments object as it's DataContext hence it can't find the command. You should explicitly define the DataContext in which your TreeViewCommand is defined. Do the following:

<!-- Note the ElementName and Path=DataContext. -->
<Button Command="{Binding ElementName=MainTreeView, Path=DataContext.TreeViewCommand}" CommandParameter="{Binding DepartmentName}" BorderThickness="0" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" >
    <Label Content="{Binding DepartmentName}"/>
</Button>

XAML for all of your nodes:

<TreeView x:Name="MainTreeView" HorizontalAlignment="Stretch" Margin="10" VerticalAlignment="Stretch" ItemsSource="{Binding Departments}">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Positions}">
            <Button Command="{Binding ElementName=MainTreeView, Path=DataContext.TreeViewCommand}" CommandParameter="{Binding DepartmentName}" BorderThickness="0" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" >
                <Label Content="{Binding DepartmentName}"/>
            </Button>
            <HierarchicalDataTemplate.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Employees}">
                    <Button Command="{Binding ElementName=MainTreeView, Path=DataContext.TreeViewCommand}" CommandParameter="{Binding PositionName}" BorderThickness="0" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" >
                        <Label Content="{Binding PositionName}"/>
                    </Button>
                    <HierarchicalDataTemplate.ItemTemplate>
                        <DataTemplate>
                            <Button Command="{Binding ElementName=MainTreeView, Path=DataContext.TreeViewCommand}" CommandParameter="{Binding EmployeeName}" BorderThickness="0" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" >
                                <Label Content="{Binding EmployeeName}"/>
                            </Button>
                        </DataTemplate>
                    </HierarchicalDataTemplate.ItemTemplate>
                </HierarchicalDataTemplate>
            </HierarchicalDataTemplate.ItemTemplate>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

Note! If you will eventually want to pass the objects instead of the strings (names of your nodes), you'll have to define ICommands for each button.

Upvotes: 1

Related Questions