1

I have the following snippet of code in an .xaml file:

<TreeView MouseDoubleClick="TreeView_MouseDoubleClick" ItemsSource="{Binding MyList}">
  <TreeView.ItemContainerStyle>
    <Style TargetType="{x:Type TreeViewItem}">
      <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
      <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
      <Setter Property="FontWeight" Value="Normal" />
      <Style.Triggers>
        <Trigger Property="IsSelected" Value="True">
          <Setter Property="FontWeight" Value="Bold" />
        </Trigger>
      </Style.Triggers>
    </Style>
  </TreeView.ItemContainerStyle>

As you can see, when you "MouseDoubleClick" on an item in the TreeView it will execute the code in the code behind...namely...

private void TreeView_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    try
    {
        MessageBox.Show(((TreeViewWithViewModelDemo.LoadOnDemand.HtmlFileViewModel)(((System.Windows.Controls.TreeView)(sender)).SelectedValue)).HtmlFileName);
    }
    catch
    {
    }
}

I'm trying to follow the Model-View-ViewModel Design Pattern and would like to move the implementation of this MouseDoubleClick event away from the View and into the ViewModel.

I understand that if I was using a command I would use {Binding Command="Select"} (or something similar that implements the ICommand interface) but I cannot seem to find the syntax for this particular issue since it is not a command button.

Can someone help me out?

Thanks

CAbbott
  • 8,078
  • 4
  • 31
  • 38
Ann Sanderson
  • 407
  • 3
  • 8
  • 17

4 Answers4

4

Here's a solution using Blend's interaction triggers.

<Page.DataContext>
    <Samples:TreeViewDblClickViewModel/>
</Page.DataContext>
<Grid>
    <TreeView ItemsSource="{Binding Items}">
        <TreeView.ItemTemplate>
            <DataTemplate>
                <ContentControl>
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="MouseDoubleClick">
                            <i:InvokeCommandAction Command="{Binding DoubleClickCommand}"/>
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                    <TextBlock Text="{Binding Name}" Background="AliceBlue" Margin="2"/>
                </ContentControl>
            </DataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>
</Grid>

View model

public class TreeViewDblClickViewModel
{
    public TreeViewDblClickViewModel()
    {
        Items = new List<TreeViewDblClickItem>
                    {
                        new TreeViewDblClickItem{ Name = "One"},
                        new TreeViewDblClickItem{ Name = "Two"},
                        new TreeViewDblClickItem{ Name = "Thee"},
                        new TreeViewDblClickItem{ Name = "Four"},
                    };
    }

    public IList<TreeViewDblClickItem> Items { get; private set; }
}

public class TreeViewDblClickItem
{
    public TreeViewDblClickItem()
    {
        DoubleClickCommand = new ActionCommand(DoubleClick);
    }

    public string Name { get; set; }

    private void DoubleClick()
    {
        Debug.WriteLine("Double click");
    }

    public ICommand DoubleClickCommand { get; private set; }
}
Phil
  • 42,255
  • 9
  • 100
  • 100
3

Using MVVM doesn't mean there mustn't be any code in the code-behind file. It just means moving all the associated logic into the viewmodel. You could just implement necessary double-click method on the viewmodel, and call it from the code behind like this:

_viewModel.MouseDoubleClickOnTree();

Also, I'd recommend looking at this topic: MVVM C# WPF binding mouse double click

Community
  • 1
  • 1
Dmitry Reznik
  • 6,812
  • 2
  • 32
  • 27
  • Is there a way to do via {Binding} on the Xaml? – Ann Sanderson Mar 21 '12 at 19:33
  • Yes. There are links in the referenced stackoverflow post. Using gestures: http://www.thejoyofcode.com/Invoking_a_Command_on_a_Double_Click_or_other_Mouse_Gesture.aspx Using ramora pattern: http://blog.lexique-du-net.com/index.php?post/2010/02/17/Use-AttachedProperties-to-add-behaviors-to-the-components – Dmitry Reznik Mar 21 '12 at 19:39
  • Any way to get gestures to use {Binding}? I tried the following and it complained... – Ann Sanderson Mar 21 '12 at 20:39
  • No. Gestures' Command aren't DependencyProperty, so they can't consume binding. You should be able to declare necessary command in xaml in ResourceDictionary and then refer it using {DynamicResource}. – Dmitry Reznik Mar 22 '12 at 05:07
0

I recommend you to start using library for MVVM pattern like Prism etc. It solves general problems and you can spend your time doing business stuff and not reinvent the wheel.

Ivan
  • 1,254
  • 12
  • 25
0

I actually posted an answer to someone about this very topic a few days ago. Here is what I posted

Obviously that is for a listviewitem, not a treeviewitem but it will still work, with some minor changes.

Community
  • 1
  • 1
Jason Ridge
  • 1,868
  • 15
  • 27