Search code examples
c#wpfxamllistviewexpander

how to select item on ExpanderDoubleClick Header in Listview


I have a ListView with different itemTemplate, and each itemTemplates have an ExpanderDoubleClick : Expander inside

I would like to select items in extended Mode in a listview with custom selection design (declared in each items UserControl). So here is my xaml for the listView:

<ListView x:Name="ListViewModules" ItemsSource="{Binding ListOfModules}"
                      ItemContainerStyle="{StaticResource ContainerListViewItemStyle}"
                      ItemTemplateSelector="{DynamicResource ModuleTemplateSelector}" 
                      SelectionMode="Extended"
                      dd:DragDrop.IsDragSource="True"
                      dd:DragDrop.IsDropTarget="True"
                      dd:DragDrop.UseDefaultDragAdorner="True"
                      Grid.Column="0" Grid.Row="0" Height="494" Width="634" Background="#FFCDCDCD" 
                      ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Visible" 
                      BorderBrush="#666666" BorderThickness="1" Padding="0"
                      ClipToBounds="True" SnapsToDevicePixels="True" >                   
</ListView>

with styles for removing the standard blue selection (declared in App.xaml):

<Style x:Key="ContainerListViewItemStyle" TargetType="{x:Type ListViewItem}">
    <Setter Property="Margin" Value="2,2,2,0"/>
    <Setter Property="dd:DragDrop.DragSourceIgnore" Value="False"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListViewItem}">
                <Border x:Name="Bd" BorderBrush="Transparent" BorderThickness="0" Background="Transparent" Padding="0" SnapsToDevicePixels="true">
                    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

I have different ItemTemplates with each "UserControl's" and here an exemple of one of them with it's selection design :

<UserControl x:Class="Topinambour.Templates.Modules.DelayTemplate" ...>
<Grid Width="602" MinHeight="24">
    <Grid.ColumnDefinitions>            <ColumnDefinition Width="40"/><ColumnDefinition />        </Grid.ColumnDefinitions>
    <ToggleButton x:Name="TgBtIsActive" IsChecked="{Binding IsChecked}" IsThreeState="{Binding IsThreeState}" Grid.Column="0" Height="24" Width="40" click="TgBtIsActive_Click"/>
    <templates:ExpanderDoubleClick x:Name="ModuleExpander" IsExpanded="{Binding IsExpanded, Mode=OneWay}" Height="auto" Template="{DynamicResource TemplateExpander}" Grid.Column="1" Margin="4,0,0,0" Collapsed="Expander_Collapsed" Expanded="Expander_Expanded" HorizontalContentAlignment="Center" VerticalContentAlignment="Center">
        <templates:ExpanderDoubleClick.Resources>
            <Style x:Key="ExpanderHeaderStyle" TargetType="{x:Type ToggleButton}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ToggleButton}">
                            <Border x:Name="BorderIndent" BorderBrush="Gray" BorderThickness="1" Height="24" Width="558" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Padding="{Binding Indent}">
                            ... my  Header Content ...
                            </Border>
                            <ControlTemplate.Triggers>
                                <DataTrigger Binding="{Binding IsExpanded}" Value="true">
                                    <Setter Property="IsEnabled" TargetName="TbComment" Value="true"/>
                                </DataTrigger>
                                <DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListViewItem}}" Value="true">
                                    <Setter Property="Background" TargetName="headerCanvas" Value="#999999"/>
                                    <Setter Property="BorderBrush" TargetName="TbComment" Value="#666666"/>
                                    <Setter Property="Foreground" TargetName="LbHeaderTitle" Value="White"/>
                                </DataTrigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </templates:ExpanderDoubleClick.Resources>
        <Border Background="White" BorderBrush="#666666" BorderThickness="1,0,1,1" Height="136" Width="558">
            <Grid>
                ... my Expanded Content ...
            </Grid>
        </Border>
    </templates:ExpanderDoubleClick>
</Grid>

and here the ExpanderDoubleClick.cs :

public class ExpanderDoubleClick: Expander
{
    private static readonly DependencyPropertyKey IsMouseDoubleClickedPropertyKey = DependencyProperty.RegisterReadOnly(
        "IsMouseDoubleClicked",typeof(Boolean),typeof(ExpanderDoubleClick),new FrameworkPropertyMetadata(false));
    public static readonly DependencyProperty IsMouseDoubleClickedProperty = IsMouseDoubleClickedPropertyKey.DependencyProperty;
    public Boolean IsMouseDoubleClicked
    {
        get { return (Boolean)GetValue(IsMouseDoubleClickedProperty); }
    }
    static ExpanderDoubleClick()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(ExpanderDoubleClick), new FrameworkPropertyMetadata(typeof(ExpanderDoubleClick)));
    }
    protected override void OnMouseDoubleClick(MouseButtonEventArgs e)
    {
        base.OnMouseDoubleClick(e);
    }
    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        ContentControl contentControl = base.GetTemplateChild("HeaderSite") as ContentControl;
        if (contentControl != null)
        {
            contentControl.AddHandler(ContentControl.MouseDoubleClickEvent, new MouseButtonEventHandler(ExpanderHeader_MouseDoubleClick), true);
        }
    }
    private void ExpanderHeader_MouseDoubleClick(Object sender, MouseButtonEventArgs e)
    {
        base.SetValue(IsMouseDoubleClickedPropertyKey, !IsMouseDoubleClicked);
        base.IsExpanded= !base.IsExpanded;
    }
}

the selection is not working when I click on the header of the expander but if I open it and click inside the expandedContent, it select the item ! what did I miss ? thank you for the reply.


Solution

  • I finally found a pretty good solution that keep my extended mode selection.

    since the header seams to not receive Click event to handle. I looked up the tree debug, and it shows that the click on header does not go through the "ListViewItem"

    so I add an OnMouseLeftButtonDown Event on my border x.Name="BorderIdent" and then add RaisedEvent back to it's itemTemplate like so :

    private void BorderIndent_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        ListViewItem lvItem = UITools.FindAncestor<ListViewItem>(e.OriginalSource as DependencyObject);
        bool isListViewItem = lvItem != null;
        if (isListViewItem)
        {
            lvItem.RaiseEvent(e);
        }
    }
    

    UITools.FindAncestor : is here

    and all worked perfectly :)