Search code examples
c#wpfxamllistboxlistboxitem

WPF ListBox item scroll/setting a new position when clicking and showing a drop down menu does not work


I have a ListBox control where I have some custom items with custom drop-down menus(my question from a couple of days ago - How to show a ListBox item outside the ListBox control and over all other controls on Item click).

Now, I have a new problem and I am attaching a video clip. so, I would like my bottom items to behave as the one above on clicking the item. So, when I click on the bottom item I want the upper item to go up in order to show the drop-down menu of the last on item. You can see that when I click the above items they change the size and move the bottom item in order to show the drop-down menu. The same principle is working on other custom listbox but here not and perhas because of thise custom items(which are only present here). Please take a look at the video clip I am sending. You can find the data template code which defines the item.enter image description here

<DataTemplate x:Key="MYListBoxItemDataTemplate" DataType="{x:Type models:MyType}">
        <StackPanel x:Name="itemsactions" HorizontalAlignment="Center" Height="135">
            <ToggleButton x:Name="choose" Height="52" Margin="0,27,0,0"
                          IsChecked="{Binding IsSelected, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}"
                          Command="{Binding DataContext.CurrentViewModel.ClickPalletTypeCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                          CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                          Style="{DynamicResource CircledTransparentToggleButtonStyle}">
                <Image x:Name="image" VerticalAlignment="Center" Margin="0,0,0,0" Height="52" Stretch="Uniform">
                    <Image.Source>
                        <BitmapImage UriSource="{Binding ImageSource.Regular}"/>
                    </Image.Source>
                </Image>
            </ToggleButton>
            <StackPanel HorizontalAlignment="Center">
                <Label Margin="0,15,0,0" Width="152" HorizontalAlignment="Center" HorizontalContentAlignment="Center" 
                       FontSize="14" FontWeight="SemiBold" 
                       Content="{Binding Weight}" 
                       Style="{DynamicResource LeftLoginTextBoxBlockLabelStyle}"/>
                <Label Margin="0,2,0,0" Width="152" HorizontalAlignment="Center" HorizontalContentAlignment="Center" 
                       FontSize="14" 
                       Content="{Binding Size}" 
                       Style="{DynamicResource LeftLoginTextBoxBlockLabelStyle}"/>
            </StackPanel>
            <StackPanel Margin="0,34,0,0" x:Name="subactions" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Collapsed">
                <ToggleButton x:Name="delete" IsTabStop="False" Width="70"
                              IsChecked="{Binding DataContext.CurrentViewModel.IsDeleteConfirmed, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                              Style="{StaticResource DeleteConfirmToggleButtonStyle}"
                              Command="{Binding DataContext.CurrentViewModel.ConfirmDeletePalletTypeCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                              CommandParameter=""/>
                <Button x:Name="edit" IsTabStop="False" HorizontalAlignment="Left" Height="40" Style="{DynamicResource EditButtonStyle}" Content="Edit"
                        Command="{Binding Path=DataContext.CurrentViewModel.EditPalletTypeCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                        CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/>
            </StackPanel>
        </StackPanel>
        <DataTemplate.Triggers>
            <DataTrigger Binding="{Binding Path=IsChecked, ElementName=choose}" Value="True">
                <Setter Property="Visibility" TargetName="subactions" Value="Visible"/>
                <Setter Property="Height" TargetName="itemsactions" Value="200"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding IsMouseOver, ElementName=choose}" Value="True">
                <Setter Property="Source" TargetName="image" Value="{Binding ImageSource.MouseOver}"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding IsPressed, ElementName=choose}" Value="True">
                <Setter Property="Source" TargetName="image" Value="{Binding ImageSource.Pressed}"/>
                <Setter Property="Visibility" TargetName="subactions" Value="Visible"/>
                <Setter Property="Height" TargetName="itemsactions" Value="200"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding IsChecked, ElementName=choose}" Value="True">
                <Setter Property="Source" TargetName="image" Value="{Binding ImageSource.Choosen}"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding IsEnabled, ElementName=choose}" Value="False">
                <Setter Property="Source" TargetName="image" Value="{Binding ImageSource.Disabled}"/>
                <Setter Property="Height" TargetName="itemsactions" Value="135"/>
            </DataTrigger>
        </DataTemplate.Triggers>
    </DataTemplate>

UPDATE - WORKING CONTROL LISTBOX:enter image description here


Solution

  • The working control has three elements in the expanded panel opposed to the two elements in the non-working container. This gives the ListBoxItem a greater height. It seems that this is enough to trigger the ListBox to scroll the item into view.

    You can try two things:

    1. add a third element to the expanded container (or generally increase the expanded item height)
    2. Handle the ListBox.SelectionChanged or ToggleButton.Clicked event, get the selected item container in the handler and call FrameworkElement.BringIntoView(). This could be enough to scroll the complete item into view automatically.
    <ListBox SelectionChanged="OnSelectionChanged" />
    
    private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
      var listBox = sender as ListBox;
      var selectedItemContainer = listBox.ItemContainerGenerator.ContainerFromItem(listBox.SelectedItem) as FrameworkElement;
      selectedItemContainer?.BringIntoView();
    }