Narendra
Narendra

Reputation: 3117

PageUp/PageDown issue when combobox inside a scrollviewer

I have a simple requirement.

I have a Combobox inside a scrollviewer. When the combobox is open and I press PageUp or PageDown then the background is also moving if the vertical scrollbar is visible.

Is there any way to stop the PageUp/PageDown to work only on the combobox when necessary?

Below is the Xaml and code-behind.

<Window x:Class="WpfApplicationDemo.ComboInScrollViewer"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Title="ComboInScrollViewer" Height="300" Width="300">
     <ScrollViewer>
         <Grid Height="500">
             <ComboBox x:Name="listContainer" Height="30" Width="90" />
         </Grid>
     </ScrollViewer>
 </Window>

CodeBehind

using System.Windows;

namespace WpfApplicationDemo
 {
     /// <summary>
     /// Interaction logic for ComboInScrollViewer.xaml
     /// </summary>
     public partial class ComboInScrollViewer : Window
     {
         public ComboInScrollViewer()
         {
             InitializeComponent();
             listContainer.Items.Add("1st");
             listContainer.Items.Add("2nd");
             listContainer.Items.Add("3rd");
             listContainer.Items.Add("4th");
             listContainer.Items.Add("5th");
             listContainer.Items.Add("6th");
         }
     }
 }

I cannot use e.handled = true directly, because the event is fired for the ScrollViewer first and then it is fired for the Combobox. I think I am missing something. Any help is appreciated.

Thanks :)

Upvotes: 1

Views: 681

Answers (2)

Narendra
Narendra

Reputation: 3117

After trying for 1-2 months here is a work around

Xaml

<Window x:Class="WpfApplicationDemo.ComboInScrollViewer"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ComboInScrollViewer" Height="300" Width="300">
    <ScrollViewer x:Name="scParent" PreviewKeyDown="ScrollViewer_PreviewKeyDown" >
        <Grid Height="500">
            <ComboBox x:Name="listContainer" Height="30" Width="90" />
            <Button Click="Button_Click" Height="30" Width="90" VerticalAlignment="Top" Margin="0,100,0,0"/>
            <TextBox x:Name="txtValue" Width="90" VerticalAlignment="Top" Margin="0,50,0,0"/>
        </Grid>
    </ScrollViewer>
</Window>

Code behind

using System.Windows;
using System.Runtime.InteropServices;
using System;
using System.Windows.Input;

namespace WpfApplicationDemo
{
    /// <summary>
    /// Interaction logic for ComboInScrollViewer.xaml
    /// </summary>
    public partial class ComboInScrollViewer : Window
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr GetActiveWindow();

        public ComboInScrollViewer()
        {
            InitializeComponent();
            listContainer.Items.Add("1st");
            listContainer.Items.Add("2nd");
            listContainer.Items.Add("3rd");
            listContainer.Items.Add("4th");
            listContainer.Items.Add("5th");
            listContainer.Items.Add("6th");
        }

        private void ScrollViewer_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (e.Key == Key.PageUp || e.Key == Key.Prior)
            {
                listContainer.RaiseEvent(new KeyEventArgs(InputManager.Current.PrimaryKeyboardDevice, PresentationSource.FromVisual(listContainer),
                    1, Key.Home) { RoutedEvent = Keyboard.KeyDownEvent }
                );
                e.Handled = true;
            }
            else if (e.Key == Key.PageDown || e.Key == Key.Next)
            {
                listContainer.RaiseEvent(new KeyEventArgs(InputManager.Current.PrimaryKeyboardDevice, PresentationSource.FromVisual(listContainer),
                    1, Key.End) { RoutedEvent = Keyboard.KeyDownEvent }
                );
                e.Handled = true;
            }
            else
            {
                e.Handled = false;
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                listContainer.RaiseEvent(new KeyEventArgs(InputManager.Current.PrimaryKeyboardDevice, PresentationSource.FromVisual(listContainer),
                    1, Key.End) { RoutedEvent = Keyboard.KeyDownEvent } 
                );
            }
            catch (Exception objExp)
            {
                // Handle Error
            }
        }
    }
}

Upvotes: 1

dev hedgehog
dev hedgehog

Reputation: 8791

Will this help you any futher?

  <ScrollViewer PreviewKeyDown="UIElement_OnPreviewKeyDown">
    <Grid Height="500">
      <ComboBox x:Name="listContainer" Height="30" Width="90"/>
    </Grid>
  </ScrollViewer>


private void UIElement_OnPreviewKeyDown(object sender, KeyEventArgs e)
{
    if ((e.Key == Key.PageUp || e.Key == Key.PageDown) && this.listContainer.IsDropDownOpen)
    {
        e.Handled = true;
    }
}

Instead of e.Handled you could place some another custom logic inside.

Its just an idea :)

Upvotes: 1

Related Questions