This is a migrated thread and some comments may be shown as answers.

Scroll events are being swallowed

11 Answers 1337 Views
WatermarkTextBox
This is a migrated thread and some comments may be shown as answers.
Simon
Top achievements
Rank 1
Simon asked on 25 Aug 2020, 02:18 PM

Our application has a form with multiple wide WatermarkTextboxes (and other textbox-like controls, e.g. MaskedDateTimeInput) in a grid layout. Most of them are single-line but some might become multiline, if the user enters long texts. The attached screenshot shows the form region where the problem becomes the most apparent.

Since each textbox, by default, has its own ScrollViewer that swallows all incoming scroll events, scrolling the main form via mouse wheel becomes pretty much impossible.

Browsers, such as Firefox, circumvent this issue by bubbling scroll events to the parent, whenever the child scrollviewer reaches its end. We could add this kind of workaround via an attached behavior but as our form is quite large, this would become ugly really soon. Is there any better solution and if not, would this be something that can be made possible in a future release?

 

 

 

 

 

 

 

 

 

 

 

11 Answers, 1 is accepted

Sort by
0
Martin Ivanov
Telerik team
answered on 28 Aug 2020, 11:19 AM

Hello Simon,

I've tested the described behavior with a native TextBox and Telerik's RadWatermarkTextBox and RadMaskedTextInput. The TextBox and the RadWatermarkTextBox didn't swallow the scroll event when the scrollviewers were reaching to the end or the beginning of the scrollable area. On the other hand the RadMaskedTextInput is a bit more differently implemented when it comes to scrolling and taking the focus, so in order to scroll the control you will need to explicitly focus it (by clicking in it). Also, when you reach the beginning of the scrollable area the scrolling bubbles to the parent scrollviewer, but when you reach the end the scrolling is handled.

Can you check the attached project and let me know if this is the behavior you are experiencing with RadMaskedInput? Also, can you tell me if the RadWatermarkTextBox  control behaves as expected on your side?

Regards,
Martin Ivanov
Progress Telerik

Five days of Blazor, Angular, React, and Xamarin experts live-coding on twitch.tv/CodeItLive , special prizes and more, for FREE?! Register now for DevReach 2.0(20).

0
Simon
Top achievements
Rank 1
answered on 31 Aug 2020, 05:18 AM

Hello Martin,

thank you very much for the example project! Since your RadWatermarkTextBox and TextBox were actually behaving exactly as I wanted them to behave, I re-checked our project and realized that I had mis-read the xaml-tree... As I just realized, we are actually using mainly RadAutoCompleteBoxes - but since they look like RadWatermarkTextBoxes and are even using RadWatermarkTextBoxes internally (which I hit with Visual Studio's WPF control picker), I came to believe that those were the problem. I am sorry for the confusion -  please feel free to move this thread to the correct forum.

However, the MaskedTextInput in your example shows the same behavior I was observing with the MaskedDateTimeInput and (as I now know) the AutoCompleteBox. I kind of get why you would not want those controls to scroll on hover. But then again, I don't think, they should begin swallowing scroll events on hover either. The current behavior could possibly cause confusion (and be really annoying if a form contains more than one wide input of those types as in our case) as neither the inner nor the outer container scroll, as soon as your mouse pointer touches a MaskedInput or an AutoCompleteBox.

 

Regards

Simon

 

 

0
Martin Ivanov
Telerik team
answered on 02 Sep 2020, 05:00 PM

Hello Simon,

It turns out that there is an issue with the default style of RadMaskedInput's TextBox control. I will need some additional time to investigate this and the behavior in the RadAutoCompleteBox control. I am going to contact you again tomorrow.  

Regards,
Martin Ivanov
Progress Telerik

Five days of Blazor, Angular, React, and Xamarin experts live-coding on twitch.tv/CodeItLive , special prizes and more, for FREE?! Register now for DevReach 2.0(20).

0
Martin Ivanov
Telerik team
answered on 03 Sep 2020, 09:33 PM

Hello Simon,

W'eve reviewed the style issue with the RadMaskedInput, but it looks like this is not related to the scrolling. We are still investigating what exactly is happening and if we can improve this. I am going to contact you again tomorrow.

Regards,
Martin Ivanov
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

0
Martin Ivanov
Telerik team
answered on 04 Sep 2020, 10:58 PM

Hello Simon,

Please excuse me for the delay. The case with the RadMaskedInput turned out to be very peculiar. It looks like a UseLayoutRounding setting in the ControlTemplate of RadMaskedNumericInput is causing the framework to disable vertical down scrolling. However, you can still scroll up. Also, the scrolling can differ based on the approach used to show the scrollbar. This said, can you share a project or some code snippets showing your setup? This will allow me to see the exact setup and suggest a specific solution.

For RadAutoCompleteBox, I was able to reproduce the scrolling behavior, but I will guess it will turn out something burried deep into the framework, so it may need some time. I will check this further.

Regards,
Martin Ivanov
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

0
Simon
Top achievements
Rank 1
answered on 07 Sep 2020, 07:59 AM

Hello Martin,
don't worry about any delay, we were in the weekend anyway :)

I attached a small sample project with a very reduced version of one of our input forms (I changed the file extension from zip to jpg as the forum would not let me upload zip files). It is missing controls between the individual  position lines but mostly mirrors our layout (minus styling, content and functionality of course). The biggest problems are the wide AutocompleteBoxes at the top of each position row which prevent you from scrolling if your mouse pointer is somewhere on the left side of the form. Additionally, since some of the date inputs at the top are implemented as MaskedDateTimeInputs, they also prevent scrolling the form if the mouse pointer is positioned at the wrong position of the form head.

0
Martin Ivanov
Telerik team
answered on 10 Sep 2020, 05:36 AM

Hello Simon,

In your case in order to bubble the scroll event to the parent ScrollViewer you will need to only set the SpinMode property of the RadMaskedDateTimeInput control to None. The spin mode is used in the MouseWheel event of the control where the event gets handled which prevents the scrolling to go up to the parent ScrollViewer. 

If you have a vertical scrollbar enabled on the mask this probably means that you have the TextBoxStyle property set. If this is your case, make sure that the custom Style is based on the default "MaskedInputTextBoxStyle" in the NoXaml scenario. If you use Xaml dlls like in your sample project, you won't be able to access the "MaskedInputTextBoxStyle" so you should manually extract it from the Telerik.Windows.Controls.Input.xaml file and use it as a base for the custom style (which enables the vertical scrollbar). Also, in the case where the vertical scrollbar is shown you will need to find the root Grid panel in the visual tree of the RadMaskedInput control and change its UseLayoutRounding property to False. You can do this by using the visual tree helper methods to get the Grid in code, or by extracting and customizing the ControlTemplate of the RadMaskedInput control. Note that this step it may be or may be not necessary based on the setup.

For the RadAutoCompleteBox, the scrolling doesn't work out of the box because the control contains a ScrollViewer in its template which brings the default WPF behavior with nested ScrollViewers where the child one handles the scroll event which never gets to the parent. To resolve this, you can get the ScrollViewer inside of the RadAutoCompleteBox (again using visual tree helper methods or extracting the ControlTemplate) and subscribe to its PreviewMouseWheel event. When the event fires, you can check if the scrollbar is hidden or if its scrolled to bottom and in both those situations manually scroll the parent scrollviewer by calling its ScrollToOffset method. 

I hope this information helps. 

Regards,
Martin Ivanov
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

0
Simon
Top achievements
Rank 1
answered on 10 Sep 2020, 12:38 PM

Hello Martin,

thank you for your answer! As the RadAutoCompleteBox is the biggest problem for our users right now, I implemented a custom behavior that uses the PreviewMouseWheel event to intercept scroll events and re-raise them on a parent ScrollViewer:

private void AttachToScrollViews(object sender, RoutedEventArgs e)
{
    AssociatedObject.Loaded -= AttachToScrollViews;
 
    _parentScrollViewer = AssociatedObject.GetVisualParent<ScrollViewer>();
 
    if (_parentScrollViewer == null)
        return;
 
    var descendantScrollViewers = AssociatedObject.ChildrenOfType<ScrollViewer>();
 
    foreach (var scrollViewer in descendantScrollViewers)
    {
        _monitoredScrollViewers.Add(scrollViewer);
        scrollViewer.PreviewMouseWheel += InterceptScroll;
    }
}
private void InterceptScroll(object sender, MouseWheelEventArgs e)
{
    var interceptedScrollViewer = sender as ScrollViewer;
    bool scrollingDown = e.Delta < 0;
    bool scrollingUp = e.Delta > 0;
 
    bool scrollingAgainstBottom = scrollingDown && (interceptedScrollViewer.ScrollableHeight == interceptedScrollViewer.VerticalOffset);
    bool scrollingAgainstTop = scrollingUp && (interceptedScrollViewer.VerticalOffset == 0.0);
    bool scrollBarInvisible = interceptedScrollViewer.ComputedVerticalScrollBarVisibility == Visibility.Collapsed ||
                              interceptedScrollViewer.ComputedVerticalScrollBarVisibility == Visibility.Hidden;
     
    var shouldIntercept = !interceptedScrollViewer.CanContentScroll
                          || scrollBarInvisible
                          || scrollingAgainstTop
                          || scrollingAgainstBottom;
 
    if (shouldIntercept)
    {
        // Mark current scroll event as handled to to suppress further handling
        e.Handled = true;
 
        //_parentScrollViewer?.ScrollToVerticalOffset(_parentScrollViewer.VerticalOffset - e.Delta);
 
        //Re-Raise the scroll event on the parent scroll viewer
        var newEvent = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
        newEvent.RoutedEvent = UIElement.MouseWheelEvent;
        _parentScrollViewer?.RaiseEvent(newEvent);
    }
}

 

And it mostly works well. However, there is still a certain cursor position where the scroll events are ignored but my event handler is not called, see the attached screenshot.

 

0
Simon
Top achievements
Rank 1
answered on 10 Sep 2020, 01:26 PM

Oh well, I clicked on the post button way too fast and cannot edit my last post so I'll continue here...

When the cursor is in the depicted position (if it still was an arrow, its tip would be directly above the textbox border), the "Hover" state of the AutoCompleteBox is not yet activated (i.e. the watermark text still has its faint color and did not yet become black). However, as you can see, the mouse cursor did already change to the text cursor. Do I have to monitor any other event or control type to make this work reliably?

 

Nevertheless, adding a behavior to each and every AutoCompleteBox is not really desirable in the long term as it adds a lot of bloat to the XAML code. Is there a chance that you might change the default behavior in the near future? At least having the option to turn scroll event bubbling on would be a useful addition imo.

 

Regarding the RadMaskedDateTime inputs: Setting SpinMode to None works for our current case and is probably enough for now. However, the spin feature might come in handy in some circumstances. So it would be great if a spin mode other than "None" would only affect mouse wheel events if the MaskedInput has the KeyboardFocus.

 

Thanks again for your help,

Simon

0
Martin Ivanov
Telerik team
answered on 15 Sep 2020, 12:24 PM

Hello Simon,

I've tested the provided code and I can confirm that there is a very small region where the text cursor appear and the PreviewMouseWheel doesn't fire, therefore the custom logic doesn't kick-in. This doing probably comes from a combination between the native WPF behavior and the layout of the RadAutoCompleteBox's template, but I can't tell what exactly happens. Anyway, I have logged an item in our feedback portal to allow built-in scrolling in those situations. I also logged an to avoid the MouseWheel event handling in the situation where the RadMaskedInput control is not focused.

I also updated your Telerik points.

Regards,
Martin Ivanov
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

0
Simon
Top achievements
Rank 1
answered on 21 Sep 2020, 05:50 AM

Hello Martin,

thank you again for your efforts and please excuse the delayed response - I was on vacation during the last week.

I will follow the tickets and am looking forward to the next releases.

Regards,

Simon Müller

 

 

Tags
WatermarkTextBox
Asked by
Simon
Top achievements
Rank 1
Answers by
Martin Ivanov
Telerik team
Simon
Top achievements
Rank 1
Share this question
or