Hi,
I want to achive that the nested RadGridView in my RadComboBox gets the focus when the ComboBox' DropDown is opened. For this I want the reference of the nested GridView but ComboBox.FindChildByType<RadGridView> doesn't work.
Here is the XAML Code of my ComboBox
<telerik:RadComboBox Name="cbMachineType" Text="{Binding Fleet}" Grid.Row="2" Grid.Column="2" IsEditable="True" Width="150" Height="{Binding ActualHeight, ElementName=txtName}" DropDownOpened="cbMachineType_DropDownOpened"> <telerik:RadComboBox.Items> <telerik:RadComboBoxItem> <telerik:RadComboBoxItem.Template> <ControlTemplate> <telerik:RadGridView x:Name="gvMachineType" ShowGroupPanel="False" CanUserFreezeColumns="False" IsReadOnly="True" IsFilteringAllowed="False" SelectionMode="Single" RowIndicatorVisibility="Collapsed" SelectedItem="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type telerik:RadComboBox}},Path=DataContext.SelectedMachineType}" DataContext="{StaticResource MachineTypeViewModel}" ItemsSource="{Binding MachineTypes}" Width="{Binding Width, ElementName=cbMachineType}" Height="150" AutoGenerateColumns="False" SelectionChanged="gvMachineType_SelectionChanged"> <telerik:RadGridView.Columns> <telerik:GridViewDataColumn Width="*" Name="cSubDescription" Header="Beschreibung" DataMemberBinding="{Binding Type}"/> <telerik:GridViewDataColumn Width="1*" Name="cSubFleet" Header="Flotte" DataMemberBinding="{Binding Fleet}"/> </telerik:RadGridView.Columns> </telerik:RadGridView> </ControlTemplate> </telerik:RadComboBoxItem.Template> </telerik:RadComboBoxItem> </telerik:RadComboBox.Items></telerik:RadComboBox>How can I achive this?
Greetings
Alexander
13 Answers, 1 is accepted
The GridView control is placed inside the Popup part of RadComboBox. In order to find it you need first to get the Popup and check inside its children:
private void cbMachineType_DropDownOpened(object sender, EventArgs e){ var comboBox = sender as RadComboBox; if (comboBox != null) { var popup = comboBox.ChildrenOfType<Popup>().FirstOrDefault(); if (popup != null) { var popUpContent = popup.Child as FrameworkElement; if (popUpContent != null) { var gridView = popUpContent.ChildrenOfType<RadGridView>().FirstOrDefault(); if (gridView != null) { //Implement logic here } } } }}Hope this helps.
Regards,
Nasko
Telerik by Progress
From the provided description of the desired behavior you need to focus and select the first row of the GridView as soon as the dropdown part is opened. If that is the case you need to call the Focus method of the GridView and set the SelectedItem property to the desired row:
private void cbMachineType_DropDownOpened(object sender, EventArgs e){ var comboBox = sender as RadComboBox; if (comboBox != null) { var popup = comboBox.ChildrenOfType<Popup>().FirstOrDefault(); if (popup != null) { var popUpContent = popup.Child as FrameworkElement; if (popUpContent != null) { var gridView = popUpContent.ChildrenOfType<RadGridView>().FirstOrDefault(); if (gridView != null) { //Implement logic here Dispatcher.BeginInvoke(new Action(() => { gridView.Focus(); gridView.SelectedItem = ((ObservableCollection<Club>)gridView.ItemsSource).First(); })); } } } }}I hope this will help you.
Regards,
Nasko
Telerik by Progress
We were not able to reproduce the observed by you behavior on our side - when the up/down keys gets pressed the Rows are selected as expected and Popup is not closed.
Please, check the attached sample that demonstrates how the approach works on our side. Try to modify the sample in order to reproduce the observed by you issue and send it back to us - thus we will be able to provide you with a prompt solution.
Hope this helps.
Regards,
Nasko
Telerik by Progress
Some of the events of RadGridView have been handled internally. Because, of that in order to handle to them by yourself you need to use the RegisterClassHandler of the EventManager class. Using that approach you could handle to the MouseLeftButtonDown event and to close a the DropDown part of RadComboBox if selection is performed:
public MainWindow(){ InitializeComponent(); this.DataContext = new MyViewModel(); EventManager.RegisterClassHandler(typeof(RadGridView), RadGridView.MouseLeftButtonDownEvent, new MouseButtonEventHandler(OnMouseLeftButtonDown), true);}private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e){ var gridView = sender as RadGridView; var row = (e.OriginalSource as UIElement).ParentOfType<GridViewRow>(); if (row != null && gridView != null && gridView.SelectedItem.Equals(row.Item)) { if (this.cbMachineType.IsDropDownOpen) { this.cbMachineType.IsDropDownOpen = false; } }}I hope this will help you.
Regards,
Nasko
Telerik by Progress
Works fine, thank you very much!
But one question is left...
For Example:
When the first or the last Item is selected and i press the up or down key with open DropDown the text of the Combobox gets cleared. How can I prevent this?
The observed by you behavior is caused by the internal logic the ComboBox executes when Up/Down keys gets pressed. In order to change that behavior you need to create a custom RadComboBox and override the HandleKeyDown method. So, when the Up/Down keys gets pressed that method should not call its base implementation that executes the default functionality of the control.
Please, check the attached sample that demonstrates the described above approach.
Hope this will help you.
Regards,
Nasko
Telerik by Progress
The behavior you are describing cannot be observed in the sample project that my colleague has provided in his previous update. Please share more details on your setup and the specific scenario when pressing enter selects the last item. Generally, pressing the enter key when RadGridView is not in edit mode would change the selection to the next item. You can check the following article - Custom Keyboard Command Provider - in order to get more information on how to override this behavior.
Regards,
Stefan Nenchev
Telerik by Progress
Hi,
I have taken a look at the CustomKeyboardCommandProvider, here is mine:
using System;using System.Collections.Generic;using System.Linq;using System.Windows.Input;using Telerik.Windows.Controls;using Telerik.Windows.Controls.GridView;namespace DyeingControl{ class CustomKeyboardCommandProvider : DefaultKeyboardCommandProvider { private GridViewDataControl parentGrid; private DefaultKeyboardCommandProvider defaultKeyboardProvider; private CustomKeyboardCommandProvider customKeyboardProvider; public CustomKeyboardCommandProvider(GridViewDataControl grid) : base(grid) { this.parentGrid = grid; } public override IEnumerable<ICommand> ProvideCommandsForKey(Key key) { List<ICommand> commandsToExecute = base.ProvideCommandsForKey(key).ToList(); if (key == Key.Enter) { commandsToExecute.Clear(); commandsToExecute.Add(RadGridViewCommands.SelectCurrentItem); } return commandsToExecute; } }}
And here I set it to the RadGridView:
RadGridView gvMachineType = null;private void cbMachineType_DropDownOpened(object sender, EventArgs e){ var comboBox = sender as RadComboBox; if (comboBox != null) { var popup = comboBox.ChildrenOfType<Popup>().FirstOrDefault(); if (popup != null) { var popUpContent = popup.Child as FrameworkElement; if (popUpContent != null) { gvMachineType = popUpContent.ChildrenOfType<RadGridView>().FirstOrDefault(); if (gvMachineType != null) { gvMachineType.KeyboardCommandProvider = new CustomKeyboardCommandProvider(gvMachineType); Dispatcher.BeginInvoke(new Action(() => { gvMachineType.Focus(); })); } } } }}
Is this ok? Or should I do it in another way? When I debug it, the comipler runs through the CustomKeyboardCommandProvider Code and all is ok...but the behavior is still the same...
Please raise a ticket with a sample project so we can have a more detailed look into your specific setup and advise you accordingly.
Regards,
Stefan Nenchev
Telerik by Progress