-2

I need to click on an TreeViewItem and open an dialog window with the data of that TreeViewItem, later based on that data I will run another command. My actual problem is: I can't click on it because treeviewitem doesn't have the command property.

My scenario: I have 2 Models with 2 properties that will be used to create my TreeViewItems. On my ViewModel I create them, and organize them inside each other based on their properties and then store them inside One Collection.

Here's my xaml to bind the elements:

<TreeView ItemsSource="{Binding Local}">
    <TreeView.DataContext>
    <data:ItemViewModel/>
    </TreeView.DataContext>
</Treeview>
//In my "Local" property I have 3 TreeViewItems with other items inside them which I want to execute the commands

I couldn't find a way to create a datatemplate for that specific scenario. Even tried to create a datatemplate with a Hyperlink (thought it would be a temporary solution) inside it, but would not execute any command.

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
D.Fernandes
  • 130
  • 8
  • You could perhaps create a property in your viewmodel (the one with the `Local` property that supplies the TreeView with the root nodes/collection for its `TreeView.ItemsSource`) which you bind against the `TreeView.SelectedItem`. Whenever the selected item in the TreeView changes, the getter of this property in your viewmodel will be called, which you can implement in such a way so that it "_does stuff_". –  Dec 05 '18 at 20:02

2 Answers2

0

MVVM pattern is to use one of the many "Event to Command" implementations out there. You basically bind the "Event to Command" object to the Click event and then a command in your VM gets bound to the "Event to Command" object and it gets mapped behind the scenes for you and handles all the enabled / disabled stuff.

You can see an example of one of the implementations here: WPF Binding UI events to commands in ViewModel

SledgeHammer
  • 7,338
  • 6
  • 41
  • 86
0

You should be binding to a collection whose objects have a collection as a public property and templating by type into whatever you want to see in each treeviewitem.

Like this sample: https://learn.microsoft.com/en-us/dotnet/api/system.windows.hierarchicaldatatemplate?view=netframework-4.7.2

Technically, you could have a button whose template was a textblock or something and that would then have the behaviour of a button such as click and command. But I'd be more likely to use an inputbinding.

Here's an example:

 <DataTemplate DataType="{x:Type local:LineTerrainVM}">
    <Grid Background="Transparent">
        <Grid.InputBindings>
            <MouseBinding MouseAction="RightClick" Command="{Binding FixLineCommand}"/>
        </Grid.InputBindings>

You can give that a commandparameter="{Binding .}" and it'll pass the viewmodel as a parameter. You could also use relativesource to the datacontext of the treeview to get at a parent viewmodel and define a command in that to do your stuff.

Since that stuff you want to do is a view responsibility you could rely on routed events without "breaking" mvvm. A click in any treeviewitem could be handled at the treeview level and use the originalsource to get to the treeviewitem clicked. Then grab it's datacontext for the viewmodel of whatever that is. Rough idea:

    <TreeView Name="tv" ItemsSource="{Binding Families}"                   FrameworkElement.PreviewMouseLeftButtonDown="Tv_PreviewMouseLeftButtonDown"

And the handler:

    private void Tv_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        var vm = ((FrameworkElement)e.OriginalSource).DataContext;
        // do something with viewmodel
    }

You could then do something like new up your dialog window, set it's datacontext to that viewmodel you just got and showdialog it.

Andy
  • 11,864
  • 2
  • 17
  • 20