We have a number of custom controls attached as RadDropDownButton items (one item per drop down button).
Some of the controls have a scrollable list. Expectation would be that the mousewheel would scroll the list when the control is displayed, but what happens is the popup disappears. We've been trying to find out how to alter this behaviour, without success. There is a similar thread (http://www.telerik.com/forums/radtreeview-in-raddropdownlist) that applies to a RadDropDownList, but the same actions for the RadDropDownButton aren't working.
Simple reproduction of the issue is adding a RadDropDownButton to a form and initializing with this code:
Any suggestions anyone may have would be greatly appreciated!
Some of the controls have a scrollable list. Expectation would be that the mousewheel would scroll the list when the control is displayed, but what happens is the popup disappears. We've been trying to find out how to alter this behaviour, without success. There is a similar thread (http://www.telerik.com/forums/radtreeview-in-raddropdownlist) that applies to a RadDropDownList, but the same actions for the RadDropDownButton aren't working.
Simple reproduction of the issue is adding a RadDropDownButton to a form and initializing with this code:
var tree =
new
RadTreeView();
for
(var i = 0; i < 100; i++)
{
tree.Nodes.Add(
new
RadTreeNode(
"Item "
+ i.ToString()));
}
var hostItem =
new
RadMenuHostItem(tree);
radDropDownButton1.Items.Add(hostItem);
Any suggestions anyone may have would be greatly appreciated!
7 Answers, 1 is accepted
0
Hello David,
Thank you for writing.
You can achieve similar functionality for RadDropDownButton by using the following code snippet:
I hope this information helps. Should you have further questions, I would be glad to help.
Regards,
Dess
Telerik
Thank you for writing.
You can achieve similar functionality for RadDropDownButton by using the following code snippet:
RadTreeView tree;
MethodInfo mi;
bool
shouldClose =
false
;
public
Form1()
{
InitializeComponent();
tree =
new
RadTreeView();
tree.NodeMouseClick += tree_NodeMouseClick;
for
(var i = 0; i < 100; i++)
{
tree.Nodes.Add(
new
RadTreeNode(
"Item "
+ i.ToString()));
}
RadMenuHostItem hostItem =
new
RadMenuHostItem(tree);
radDropDownButton1.Items.Add(hostItem);
mi = tree.TreeViewElement.GetType().GetMethod(
"ProcessMouseWheel"
,
BindingFlags.NonPublic | BindingFlags.Instance);
this
.radDropDownButton1.DropDownOpened += radDropDownButton1_DropDownOpened;
this
.radDropDownButton1.DropDownButtonElement.DropDownMenu.DropDownClosing += DropDownMenu_DropDownClosing;
}
private
void
tree_NodeMouseClick(
object
sender, RadTreeViewEventArgs e)
{
shouldClose =
true
;
this
.radDropDownButton1.DropDownButtonElement.DropDownMenu.ClosePopup(RadPopupCloseReason.Mouse);
}
private
void
DropDownMenu_DropDownClosing(
object
sender, RadPopupClosingEventArgs args)
{
args.Cancel = !shouldClose;
shouldClose =
false
;
}
private
void
radDropDownButton1_DropDownOpened(
object
sender, EventArgs e)
{
RadDropDownButton ddb = sender
as
RadDropDownButton;
ddb.MouseWheel -= ddle_MouseWheel;
ddb.MouseWheel += ddle_MouseWheel;
}
private
void
ddle_MouseWheel(
object
sender, MouseEventArgs e)
{
if
(tree !=
null
&& mi !=
null
)
{
mi.Invoke(tree.TreeViewElement,
new
object
[] { e });
}
}
I hope this information helps. Should you have further questions, I would be glad to help.
Dess
Telerik
Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.
0
David
Top achievements
Rank 1
answered on 18 Feb 2015, 04:24 PM
Thank you so much, this is very helpful, it definitely brings us one step closer; when working with the code from the other thread we didn't think to have the "shouldClose" flag that keeps the dropdown open.
The only problem now is that the behaviour of the control has changed from what users would expect. The only way to close the control is by clicking a treeview item. Clicking outside the control should cause the dropdown to close, but it no longer does so (because of the "shouldClose" flag).
Looking at the CloseReason in the Closing event, the reason is "Mouse" for both clicking outside the control and for performing a mouse wheel action within the control, so there doesn't seem to be a way to change behaviour there. (Ideally there would be a way to signal that the mouse wheel event was handled by the control and not bubbled up to the RadDropDownButton.)
Is there any other way to prevent the dropdown from closing on mousewheel that you are aware of?
The only problem now is that the behaviour of the control has changed from what users would expect. The only way to close the control is by clicking a treeview item. Clicking outside the control should cause the dropdown to close, but it no longer does so (because of the "shouldClose" flag).
Looking at the CloseReason in the Closing event, the reason is "Mouse" for both clicking outside the control and for performing a mouse wheel action within the control, so there doesn't seem to be a way to change behaviour there. (Ideally there would be a way to signal that the mouse wheel event was handled by the control and not bubbled up to the RadDropDownButton.)
Is there any other way to prevent the dropdown from closing on mousewheel that you are aware of?
0
David
Top achievements
Rank 1
answered on 18 Feb 2015, 04:45 PM
I should also mention, most of our dropdowns are UserControls containing multiple child controls. When the above works is applied to them, it works the same... and has the same problem of the dropdown not closing in with the mouse clicking outside the control, hitting Escape, and so forth. (We have a completion event on these user controls, so closing through the control is no problem... it's the external close conditions that cause us problems.)
I'm mentioning this because one thought we had was using the MouseEnter/MouseLeave and Key events to alter the state of the shouldClose flag, but that doesn't work well for a UserControl with multiple child controls. If only the MouseEventsArgs for the wheel event had a "handled" flag.
I'm mentioning this because one thought we had was using the MouseEnter/MouseLeave and Key events to alter the state of the shouldClose flag, but that doesn't work well for a UserControl with multiple child controls. If only the MouseEventsArgs for the wheel event had a "handled" flag.
0
David
Top achievements
Rank 1
answered on 18 Feb 2015, 10:12 PM
We found a workaround, but it's a bit involved... so we would still like to know if there is a better solution or approach.
The issue seems to be rooted in the RadDropDownMenu class, where the OnMouseWheel method has this bit of code:
This does seem a bit odd... and doesn't "work" like other Windows programs, menus typically do not auto-close like this when the mouse wheel is moved, but I've verified that it seems to be this was throughout the Telerik product by looking at the WinForms demo. Perhaps there is a reason I can't see for this behaviour, or is it a bug? The mouse wheel closes a menu, unless it's on a menu item with children in which case it does nothing... seems inconsistent.
Note that the RadApplicationMenu has similar code to the RadDropDownMenu, but it does the opposite action:
In any case, our workaround for this seems to work well; we're just not sure if it's the best solution. It does capture the mouse wheel events, allows for a complex user control (hooking the wheel to a specific child control, which works for our use case), and doesn't interfere with the closing of the popup. (Note there is a bit more in the test than strictly needed, since it's part of a larger general purpose usage.)
These are the test form and test user control:
And the subclassed Telerik controls that these are using:
Again, please let us know if there is a better approach than the above. And thank you again for your help earlier.
Dave
The issue seems to be rooted in the RadDropDownMenu class, where the OnMouseWheel method has this bit of code:
if
(element.ScrollPanel.VerticalScrollBar.Visibility != ElementVisibility.Visible)
{
return
false
;
}
This does seem a bit odd... and doesn't "work" like other Windows programs, menus typically do not auto-close like this when the mouse wheel is moved, but I've verified that it seems to be this was throughout the Telerik product by looking at the WinForms demo. Perhaps there is a reason I can't see for this behaviour, or is it a bug? The mouse wheel closes a menu, unless it's on a menu item with children in which case it does nothing... seems inconsistent.
Note that the RadApplicationMenu has similar code to the RadDropDownMenu, but it does the opposite action:
if
(element.MenuElement.ScrollPanel.VerticalScrollBar.Visibility != ElementVisibility.Visible)
{
return
true
;
}
In any case, our workaround for this seems to work well; we're just not sure if it's the best solution. It does capture the mouse wheel events, allows for a complex user control (hooking the wheel to a specific child control, which works for our use case), and doesn't interfere with the closing of the popup. (Note there is a bit more in the test than strictly needed, since it's part of a larger general purpose usage.)
These are the test form and test user control:
public
partial
class
Form1 : Form
{
public
Form1()
{
InitializeComponent();
var testControl =
new
TestUserControl();
singleItemDropDownButton1.HostedControl = testControl;
testControl.Completed += (sender, o) =>
{
label1.Text = (o ==
null
?
null
: o.ToString());
};
}
}
public
partial
class
TestUserControl : UserControl, IPopupCompletion
{
public
event
EventHandler<
object
> Completed;
private
void
OnCompleted(
object
value)
{
var handler = Completed;
if
(handler !=
null
)
{
handler(
this
, value);
}
}
public
TestUserControl()
{
InitializeComponent();
for
(var i = 0; i < 100; i++)
{
radTreeView1.Nodes.Add(
new
RadTreeNode(String.Format(
"Item {0}"
, i)));
}
radTreeView1.NodeMouseClick += (sender, args) => OnCompleted(args.Node.Text);
MouseWheel += (sender, args) => radTreeView1.CallOnMouseWheel(args);
}
}
And the subclassed Telerik controls that these are using:
public
class
SingleItemDropDownButton : RadDropDownButton
{
public
Control HostedControl
{
set
{
if
(Items.Count > 0)
{
Items.Clear();
}
Items.Add(
new
RadMenuHostItem(value));
((SingleItemDropDownButtonPopup) DropDownButtonElement.DropDownMenu).HostedControl = value;
var popupCompletion = value
as
IPopupCompletion;
if
(popupCompletion !=
null
)
{
popupCompletion.Completed += (sender, o) => HideDropDown();
}
}
}
protected
override
RadDropDownButtonElement CreateButtonElement()
{
return
new
SingleItemDropDownButtonElement();
}
}
public
class
SingleItemDropDownButtonElement : RadDropDownButtonElement
{
protected
override
RadDropDownButtonPopup CreateDropDown()
{
var dropDownMenu =
new
SingleItemDropDownButtonPopup(
this
);
if
(IsInValidState(
true
))
{
dropDownMenu.ImageList = ElementTree.ComponentTreeHandler.ImageList;
}
return
dropDownMenu;
}
protected
override
Type ThemeEffectiveType
{
get
{
return
typeof
(RadDropDownButtonElement); }
}
}
public
class
SingleItemDropDownButtonPopup : RadDropDownButtonPopup
{
private
Control _hostedControl;
private
MethodInfo _methodInfo;
public
Control HostedControl
{
set
{
_hostedControl = value;
_methodInfo = value.GetType()
.GetMethod(
"OnMouseWheel"
, BindingFlags.NonPublic | BindingFlags.Instance,
null
,
new
[] {
typeof
(MouseEventArgs)},
null
);
}
}
public
SingleItemDropDownButtonPopup(RadDropDownButtonElement ownerElement)
:
base
(ownerElement)
{
}
public
override
bool
OnMouseWheel(Control target,
int
delta)
{
if
(_hostedControl ==
null
|| _methodInfo ==
null
)
{
return
false
;
}
var mouseEventArgs =
new
MouseEventArgs(MouseButtons, 0, MousePosition.X, MousePosition.Y, delta);
_methodInfo.Invoke(_hostedControl,
new
object
[] {mouseEventArgs});
return
true
;
}
}
public
interface
IPopupCompletion
{
event
EventHandler<
object
> Completed;
}
Again, please let us know if there is a better approach than the above. And thank you again for your help earlier.
Dave
0
David
Top achievements
Rank 1
answered on 18 Feb 2015, 10:14 PM
(Sorry... that observation about the differences between RadDropDownMenu and RadApplicationMenu handling of OnMouseWheel, should have instead referenced the RadApplicationMenuDropDown class.)
0
Accepted
Hello David,
Thank you for writing back.
By default, RadDropDownButton is not supposed to close automatically when its pop up does not show all items and you perform scrolling. However, for the specific case, you should keep the pop up shown manually. Your approach seems good. Feel free to use it if it suits your requirement.
An alternative solution that I can suggest is to handle globally the MouseDown event and manipulate the shouldClose flag if the element under the mouse is not the RadTreeView. You can have a look at the following links related to this topic:
I hope this information helps. If you have any additional questions, please let me know.
Regards,
Dess
Telerik
Thank you for writing back.
By default, RadDropDownButton is not supposed to close automatically when its pop up does not show all items and you perform scrolling. However, for the specific case, you should keep the pop up shown manually. Your approach seems good. Feel free to use it if it suits your requirement.
An alternative solution that I can suggest is to handle globally the MouseDown event and manipulate the shouldClose flag if the element under the mouse is not the RadTreeView. You can have a look at the following links related to this topic:
- http://www.codeproject.com/Articles/7294/Processing-Global-Mouse-and-Keyboard-Hooks-in-C
- https://social.msdn.microsoft.com/Forums/en-US/c2506ba7-cfbe-4920-a4eb-71d285a4bb3b/how-do-you-detect-global-mouse-clicks-ie-outside-of-your-form?forum=csharpgeneral
- http://stackoverflow.com/questions/7497024/how-to-detect-mouse-clicks
I hope this information helps. If you have any additional questions, please let me know.
Regards,
Dess
Telerik
Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.
0
David
Top achievements
Rank 1
answered on 23 Feb 2015, 05:33 PM
We understand. I think we will continue to use our implementation, since it is working very well. (We also had to override the OnKeyDown method of RadDropDownButtonPopup as well, since we wanted to handle the escape and enter keys and couldn't otherwise stop the RadDropDownButton from handling the event.)
Thank you again Dess for all your help, it definitely put us on the right track. Your assistance in this is greatly appreciated!
Thank you again Dess for all your help, it definitely put us on the right track. Your assistance in this is greatly appreciated!