Tab in and Click on DropDown Button which is made the Custom Drop Down

6 posts, 0 answers
  1. Syed Danish
    Syed Danish avatar
    70 posts
    Member since:
    Dec 2009

    Posted 28 May 2010 Link to this post

    Hi,

    I am using the rad drop down button and made a custom control out of it. This control gives me a peculier problem, the drop down button in its popup opens the grid control. I also made the control with the arrow keys to work on tab out but the problem is that if the arrow key is made to work and again if the user needs to click on the rad drop down button this throws an error. I tried to override the OnClick event but that was of no use and gave me the same error. The error message is "Error HRESULT E_FAIL has been returned from a call to a COM component." Please help me, thanks in advance.

    Thanks and Regards,
    Syed Danish
  2. Bobi
    Admin
    Bobi avatar
    513 posts

    Posted 02 Jun 2010 Link to this post

    Hello Syed Danish,

    We are unable to reproduce this issue. Is is possible to send us some sample code or explain in more details the structure of your application?

    Best wishes,
    Bobi
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  3. DevCraft banner
  4. Syed Danish
    Syed Danish avatar
    70 posts
    Member since:
    Dec 2009

    Posted 25 Jun 2010 Link to this post

    using System;  
    using System.Net;  
    using System.Windows;  
    using System.Windows.Controls;  
    using System.Windows.Documents;  
    using System.Windows.Ink;  
    using System.Windows.Input;  
    using System.Windows.Media;  
    using System.Windows.Media.Animation;  
    using System.Windows.Shapes;  
    using Telerik.Windows.Controls;  
    using System.Linq;  
    using System.ComponentModel;  
    using System.Collections;  
    using System.Collections.Generic;  
    using System.Reflection;  
     
    namespace Controlkit.Module  
    {  
        [Description("This is a Custom Dropdown Control with a Grid")]  
        public class CustomDropdown : RadDropDownButton  
        {  
            protected TextBlock lblContent;  
            protected DataGrid grid;  
            protected int itemCount;  
     
     
            public CustomDropdown()  
                : base()  
            {  
                this.lblContent = new TextBlock();  
                this.lblContent.Padding = new Thickness(10, 0, 0, 0);  
                this.HorizontalContentAlignment = HorizontalAlignment.Left;  
                this.Content = this.lblContent;  
     
                //now the grid              
                this.grid = new DataGrid();  
                this.grid.HeadersVisibility = DataGridHeadersVisibility.Column;  
                this.grid.IsReadOnly = true;  
                this.grid.SelectionMode = DataGridSelectionMode.Single;  
                this.grid.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden;  
     
     
                this.grid.SelectionChanged += new System.Windows.Controls.SelectionChangedEventHandler(grid_SelectionChanged);  
                this.grid.LayoutUpdated += new EventHandler(grid_LayoutUpdated);  
                //this.grid.GridLinesVisibility = DataGridGridLinesVisibility.None;  
                SolidColorBrush grdBack = new SolidColorBrush(Colors.Transparent);  
                this.grid.RowBackground = grdBack;  
                this.grid.AlternatingRowBackground = grdBack;  
                this.DropDownContent = this.grid;  
     
                this.Height = 25;  
                this.itemCount = 0;  
            }  
     
            protected override void OnKeyDown(KeyEventArgs e)  
            {  
                //base.OnKeyDown(e);  
                switch (e.Key)  
                {  
                    case Key.Down:  
                        if (this.grid.SelectedIndex < this.itemCount) this.grid.SelectedIndex++;  
                        break;  
                    case Key.Up:  
                        if (this.grid.SelectedIndex > -1) this.grid.SelectedIndex--;  
                        break;  
                }  
            }  
     
            void grid_LayoutUpdated(object sender, EventArgs e)  
            {  
                double width = 15;  
                foreach (var col in this.grid.Columns)  
                {  
                    width += col.ActualWidth;  
                }  
                this.grid.Width = (width > this.MinWidth) ? width : this.MinWidth;  
                if (grid.ItemsSource != null)  
                {  
                    double height = 12;  
                    foreach (var item in grid.ItemsSource)  
                    {  
                        height += 25;  
                        if (height > 160) break;  
                    }  
                    grid.Height = height;  
                }  
            }  
     
            /// <summary>  
            /// This is the event handler for grids selection change.   
            /// </summary>  
            /// <param name="sender"></param>  
            /// <param name="e"></param>  
            void grid_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)  
            {  
                if (e.AddedItems.Count > 0)  
                {  
                    this.lblContent.DataContext = e.AddedItems[0];  
                    _selection = e.AddedItems[0];  
                    SelectedValue = GetMemberValue(_selection);  
                }  
                else 
                {  
                    _selection = null;  
                    SelectedValue = null;  
                }  
                this.OnSelectionChanged(e);  
                this.IsOpen = false;  
            }  
     
            /// <summary>  
            /// for implementing the onevent pattern  
            /// </summary>  
            /// <param name="e"></param>  
            protected virtual void OnSelectionChanged(System.Windows.Controls.SelectionChangedEventArgs e)  
            {  
                if (this.SelectionChanged != null)  
                {  
                    this.SelectionChanged(this, e);  
                }  
            }  
            /// <summary>  
            /// The text property. It returns the text of the   
            /// current combobox selection  
            /// </summary>  
            public string Text  
            {  
                get 
                {  
                    return this.lblContent.Text;  
                }  
                set 
                {  
                    this.lblContent.Text = value;  
                }  
            }  
     
     
            public static DependencyProperty GridHeightProperty =  
              DependencyProperty.Register("GridHeight"typeof(double), typeof(PhoenixCustomDropdown), new PropertyMetadata(  
                  (o, e) =>  
                  {  
                      ((PhoenixCustomDropdown)o).grid.Height = (double)e.NewValue;  
                  }  
                  ));  
     
            /// <summary>  
            /// The height of the grid  
            /// </summary>  
            public double GridHeight  
            {  
                get 
                {  
                    return (double)GetValue(GridHeightProperty);  
                }  
                set 
                {  
                    SetValue(GridHeightProperty, value);  
                }  
            }  
     
            public static DependencyProperty ItemsSourceProperty =  
              DependencyProperty.Register("ItemsSource"typeof(IEnumerable), typeof(PhoenixCustomDropdown), new PropertyMetadata(  
                  (o, e) =>  
                  {  
                      PhoenixCustomDropdown cdd = (PhoenixCustomDropdown)o;  
                      IList lst = (IList)e.NewValue;  
                      cdd.itemCount = lst.Count;  
                      if (cdd.DefaultValueText != null)  
                      {  
                          var first = lst[0];  
                          var blank = Activator.CreateInstance(first.GetType());  
                          blank.GetType().GetProperty(cdd.DisplayMemberPath).SetValue(blank, cdd.DefaultValueText, null);  
                          //blank.GetType().GetProperty(cdd.ValueMemberPath).SetValue(blank, null, null);  
     
                          List<object> result = new List<object>();  
                          result.Add(blank);  
                          result.AddRange(lst);  
                          cdd.grid.ItemsSource = result;  
                          if (cdd.SelectedValue == null) cdd.SelectedValue = blank.GetType().GetProperty(cdd.ValueMemberPath).GetValue(blank, null);  
                      }  
                      else 
                      {  
                          cdd.grid.ItemsSource = lst;  
                      }  
                      if (cdd.DefaultDisplayColumn != null)  
                      {  
                          var deflt = (  
                              from object itm in cdd.grid.ItemsSource  
                              where (bool)itm.GetType().GetProperty(cdd.DefaultDisplayColumn).GetValue(itm, null)  
                              select itm  
                                       ).FirstOrDefault();  
                          if (deflt != null)  
                          {  
                              if (cdd.SelectedValue == null) cdd.SelectedValue = deflt.GetType().GetProperty(cdd.ValueMemberPath).GetValue(deflt, null);  
                          }  
                      }  
                      cdd.SetSelectionFromValue();  
                  }  
                  ));  
     
            /// <summary>  
            /// The items source to be used for displaying the items in the grid  
            /// </summary>  
            public IEnumerable ItemsSource  
            {  
                get 
                {  
                    return this.grid.ItemsSource;  
                }  
                set 
                {  
                    SetValue(ItemsSourceProperty, value);  
                }  
            }  
     
            public static DependencyProperty SelectedItemProperty =  
              DependencyProperty.Register("SelectedItem"typeof(object), typeof(PhoenixCustomDropdown), new PropertyMetadata(  
                  (o, e) =>  
                  {  
     
                  }  
                  ));  
     
            /// <summary>  
            /// This property gives the selected item  
            /// </summary>  
            [Description("This will return a single selected item from the items source")]  
            public object SelectedItem  
            {  
                get 
                {  
                    return ((object)(GetValue(PhoenixCustomDropdown.SelectedItemProperty)));  
                }  
                set 
                {  
                    SetValue(PhoenixCustomDropdown.SelectedItemProperty, value);  
                }  
            }  
     
     
            public static DependencyProperty DisplayMemberPathProperty =  
              DependencyProperty.Register("DisplayMemberPath"typeof(string), typeof(PhoenixCustomDropdown), null);  
     
            /// <summary>  
            /// Here you can set column name of the grid to be displayed in the selected textbox  
            /// </summary>  
            public string DisplayMemberPath  
            {  
                get 
                {  
                    return ((string)(base.GetValue(PhoenixCustomDropdown.DisplayMemberPathProperty)));  
                }  
                set 
                {  
                    base.SetValue(PhoenixCustomDropdown.DisplayMemberPathProperty, value);  
                    this.lblContent.SetBinding(TextBlock.TextProperty, new System.Windows.Data.Binding() { Source = this.lblContent.DataContext, Path = new PropertyPath(value) });  
                }  
            }
            #region copied code  
     
            private object _selection;  
     
            /// <summary>  
            /// Returns the value from a particular record  
            /// </summary>  
            /// <param name="item">The single record to evaluate</param>  
            /// <returns>The value memeber value</returns>  
            private object GetMemberValue(object item)  
            {  
                return item.GetType().GetProperty(ValueMemberPath).GetValue(item, null);  
            }  
     
            private object GetMemberDisplay(object item)  
            {  
                try 
                {  
                    return item.GetType().GetProperty(DisplayMemberPath).GetValue(item, null);  
                }  
                catch (Exception)  
                {  
                    return null;  
                }  
            }  
     
     
     
            public static DependencyProperty ValueMemberPathProperty =  
              DependencyProperty.Register("ValueMemberPath"typeof(string), typeof(PhoenixCustomDropdown), null);  
     
            /// <summary>  
            /// The name of the colum whos value will be returned while a single item is selected  
            /// </summary>  
            public string ValueMemberPath  
            {  
                get 
                {  
                    return ((string)(base.GetValue(PhoenixCustomDropdown.ValueMemberPathProperty)));  
                }  
                set 
                {  
                    base.SetValue(PhoenixCustomDropdown.ValueMemberPathProperty, value);  
                }  
            }  
     
            public static DependencyProperty SelectedValueProperty =  
              DependencyProperty.Register("SelectedValue"typeof(object), typeof(PhoenixCustomDropdown),  
              new PropertyMetadata((o, e) =>  
              {  
                  ((PhoenixCustomDropdown)o).SetSelectionFromValue();  
              }));  
     
            /// <summary>  
            /// The selected value,based on the selection  
            /// </summary>  
            public object SelectedValue  
            {  
                get 
                {  
                    return ((object)(base.GetValue(PhoenixCustomDropdown.SelectedValueProperty)));  
                }  
                set 
                {  
                    base.SetValue(PhoenixCustomDropdown.SelectedValueProperty, value);  
                }  
            }  
     
            private void SetSelectionFromValue()  
            {  
                var value = SelectedValue;  
                if (ItemsSource != null && value != null)  
                {  
                    var sel = (from object item in ItemsSource  
                               where GetMemberValue(item).Equals(value)  
                               select item).Single();  
                    _selection = sel;  
                    SelectedItem = sel;  
                    this.lblContent.Text = this.GetMemberDisplay(sel).ToString();  
                }  
            }
            #endregion  
     
            [Description("Please do handle this event in case you want to do something specific while the selection of the combobox is changed")]  
            public event System.Windows.Controls.SelectionChangedEventHandler SelectionChanged;  
     
            protected string _cols;  
            /// <summary>  
            /// This is where we are going to pass the columns  
            /// The format should be col1,col2,col3 etc.  
            /// </summary>  
            public string Columns  
            {  
                set 
                {  
                    this._cols = value;  
     
                    this.grid.AutoGenerateColumns = false;  
     
                    foreach (string col in value.Split(','))  
                    {  
                        string[] vals = col.Split('|');  
                        DataGridTextColumn dtcol = new DataGridTextColumn();  
                        dtcol.Binding = new System.Windows.Data.Binding(vals[0]);  
                        dtcol.Width = DataGridLength.SizeToCells;  
                        dtcol.Header = (vals.Length > 1 ? vals[1] : vals[0]);  
                        this.grid.Columns.Add(dtcol);  
                    }  
                    if (grid.Columns.Count == 1)  
                    {  
                        this.grid.HeadersVisibility = DataGridHeadersVisibility.None;  
                        this.grid.GridLinesVisibility = DataGridGridLinesVisibility.None;  
                    }  
                }  
                get 
                {  
                    return this._cols;  
                }  
            }  
     
            /// <summary>  
            /// This is the text which is going to come when there   
            /// is no other values added to it.   
            /// for example it will display none if you select nothing.  
            /// </summary>  
            [Description("Add the default value text which will be displayed by default in case there is no data selected")]  
            public string DefaultValueText  
            {  
                get;  
                set;  
            }  
     
            [Description("Here you can add the default display column name which will be used for selecting the default value")]  
            public string DefaultDisplayColumn  
            {  
                set;  
                get;  
            }  
        }  
    }  
     
    The above is the code for the custom drop down which i made. The drop down content here is the Data Grid. I need the arrow keys in this to work, this works fine but when the user tabs in to the control and accesses the arrow keys and again if the user wants to use his mouse to work on the same control this gives an error "Error HRESULT E_FAIL has been returned from a call to a COM component."
     The XAML line for this control is some thing like this.
            <Kit:CustomDropdown x:Name="cmbDepartment" Grid.Row="1" Grid.Column="4" Style="{StaticResource ComboStyle}" HorizontalAlignment="Left" Margin="6,6,6,6" Width="Auto" ItemsSource="{Binding Source={StaticResource GetOrganisationDepartmentList}, Path=Data}" Columns="Code" DisplayMemberPath="Code" ValueMemberPath="Code" DefaultDisplayColumn="DefaultDisplay" DefaultValueText="Select"/>  

    Please help me out.

    Thanks and Regards,
    Syed Danish
  5. Miro Miroslavov
    Admin
    Miro Miroslavov avatar
    588 posts

    Posted 30 Jun 2010 Link to this post

    Hello Syed Danish,

    As far as I see, the problem could be in the LayoutUpdated event handler. Because in the handler, there is code that will rise the event again and again - this will end in recursive Layout updates. And the selection from the other hand could cause the Layou pass, which will call the handler.
    I strongly suggest you not to use the LayoutUpdated event for such a scenarios.
    But to make sure what causes the problem, it will be better if we can debug it, so if you can send us the example project?
    Thank you.

    Sincerely yours,
    Miro Miroslavov
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  6. Syed Danish
    Syed Danish avatar
    70 posts
    Member since:
    Dec 2009

    Posted 01 Jul 2010 Link to this post

    Hi Miro Miroslavov,
    This dosent really helped me. Can you tell me how to upload the project so that I can show you the exact behaviour of the custom control.
  7. Miro Miroslavov
    Admin
    Miro Miroslavov avatar
    588 posts

    Posted 02 Jul 2010 Link to this post

    Hi Syed Danish,

    You have to create a new support ticket and you will see the option to attach file.

    Regards,
    Miro Miroslavov
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
Back to Top
DevCraft banner