views:

145

answers:

2

Im using the latest version of mvvm light toolkit, however i'm not clear how I can use EventToCommand for the event TreeViewItem.Expanded.

THis dosent work... what am I doing wrong?

<TreeView Grid.Column="0" Grid.Row="0" ItemsSource="{Binding Path= MonitoredDatabases}">
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding Queues}">

                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding ServerName}" />
                    <TextBlock Text="\" />
                    <TextBlock Text="{Binding DatabaseName}" />
                </StackPanel>

                <HierarchicalDataTemplate.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding QueueName}" />
                    </DataTemplate>
                </HierarchicalDataTemplate.ItemTemplate>

            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="TreeViewItem.Expanded">
                <cmd:EventToCommand Command="{Binding Path=NodeExpanded}"
                                    CommandParameter="Expanded" />
            </i:EventTrigger>
            <i:EventTrigger EventName="TreeViewItem.Collapsed">
                <cmd:EventToCommand Command="{Binding Path=NodeCollapsed}"
                                    CommandParameter="Collapsed" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </TreeView>

help much appreciated.

Regards.

Gary

A: 

The event to command behavior is implemented as an attached property, which must be attached to a FrameworkElement. Your sample has the Triggers attached property attached to the TreeView which doesn't have an Expanded or Collapsed event. You attempted to use "TreeViewItem.Expanded" as the event name, but it doesn't work that way.

If you were creating your TreeViewItems statically in XAML, or manually in code-behind, you could attach to each TreeViewItem. Unfortunately, I'm not aware of any way to attach to the TreeViewItem from the HierarchicalDataTemplate. You can bind to the TemplatedParent RelativeSource, but you can't attach to it. Your only solution is to iterate through the TreeViewItems in code-behind, and manually handle the events, but even then you'd have to do so using the VisualTreeHelper only after the TreeView control has been data bound and rendered, which is a huge hack.

Matt Casto
A: 

I was able to do this by creating a custom ItemContainerStyle for the TreeView. You should be able to put this together with the following code snippets.

1. A ViewModel for the TreeView

public class TreeViewModelView
{
    public IEnumerable<object> Values
    {
        get { /* return hierarchical data source here ... */ }
    }

    /// <summary>
    /// Command executed when the TreeViewItem expanding event is raised. The data item is passed in as a parameter.
    /// </summary>
    public RelayCommand<object> ExpandedCommand
    {
        get { return new RelayCommand<object>( o => MessageBox.Show( o.GetType().Name ) ); }
    }

    /// <summary>
    /// Command executed when the TreeViewItem collapsing event is raised.
    /// </summary>
    public RelayCommand CollapsedCommand
    {
        get { return new RelayCommand( () => MessageBox.Show( "Collapsed" ) ); }
    }

}

2. Define the TreeView and setup the required data binding:

 <TreeView x:Name="lstItems" HorizontalAlignment="Left" Margin="21,19,0,80" Width="283" 
          DataContext="{DynamicResource TreeViewModelView}"
          ItemsSource="{Binding Values, Mode=OneWay}" 
          ItemTemplate="{DynamicResource TreeViewDataTemplate}" 
          ItemContainerStyle="{DynamicResource TreeViewItemStyle}">
    <TreeView.Resources>
        <mv:TreeViewModelView x:Key="TreeViewModelView" />

        <HierarchicalDataTemplate x:Key="TreeViewDataTemplate" ItemsSource="{Binding Items}">
            <Grid>
                <TextBlock Text="{Binding Name}" />
            </Grid>
        </HierarchicalDataTemplate>
    </TreeView.Resources>
</TreeView>

3. In Expression Blend you can create edit a copy of the ItemContainerStyle template

<Style x:Key="TreeViewItemStyle" TargetType="{x:Type TreeViewItem}">

    ...

</Style>

4. Then replace the ToggleButton with:

<ToggleButton x:Name="Expander" ClickMode="Press" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ExpandCollapseToggleStyle}">

    <i:Interaction.Triggers>
        <!-- When the Checked event is raised execute the ExpandedCommand with the data item as a parameter. -->
        <i:EventTrigger EventName="Checked">
            <GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding Path=DataContext.ExpandedCommand, RelativeSource={RelativeSource AncestorType={x:Type TreeView}}, Mode=OneWay}" 
                CommandParameter="{Binding}" />
        </i:EventTrigger>
        <!-- When the Unchecked event is raised execute the CollapsedCommand. -->
        <i:EventTrigger EventName="Unchecked">
            <GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding Path=DataContext.CollapsedCommand, RelativeSource={RelativeSource AncestorType={x:Type TreeView}}, Mode=OneWay}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>

</ToggleButton>
bstoney