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

Design Time Column Types for Bound Grid

1 Answer 91 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Paul
Top achievements
Rank 1
Paul asked on 15 Sep 2014, 09:13 PM
When you bind the GridView to a data source at design time, the columns get auto generated - it creates a new Project Data Source from an Object and generates a form BindingSource.

However, on the object I have a reference to another object - ClassA -> ClassB Property which references a ClassB instance.

At design time, a TextBox column is generated.  Where as at runtime, I need this to be a DropDown list.  Is it possible to change the column type at design time or make it generate a DropDown for the object reference property - without creating an Unbound Column?

Thanks

Andez

1 Answer, 1 is accepted

Sort by
0
Dess | Tech Support Engineer, Principal
Telerik team
answered on 18 Sep 2014, 10:31 AM
Hello Andez,

Thank you for writing.

When you bind our RadGridView at design time (let's bind to a collection of objects 'A'), it generates automatically the columns according to the specific property type.
Class A has the following properties:
int 'Id'
string 'Name'
B 'Info'

Class B has the following properties:
int 'UniqueIdentifier'
string 'Description'

If you have a property of custom type (property 'Info' in this case), it is normal that the grid generates a text box column for it. You can change the RadGridView.Columns collection at design time and add a GridViewComboBoxColumn. However, in order to set up the correct binding, the GridViewComboBoxColumn.FieldName should be in correspondence with the certain property (FieldInfo = 'Info'). Here comes the problem. The GridViewComboBoxColumn's DisplayMember and ValueMember properties indicates what value is expected in the cell and what should be displayed in the cell. If you set the ValueMember property to 'UniqueIdentifier' and the cell itself has an object of type B, it is not possible to setup the correct binding in this case at design time.

The possible solution that I can suggest is to bind the grid at design time to a collection of objects 'A' and leave the automatically generated columns. Thus, you will have the text box column for the property of custom type. However, it is necessary to implement a TypeConverter which can convert the custom type 'B' to string and vice versa. Additionally, you can replace the default text box editor with a RadDropDownListEditor. Please find below a sample implementation. Note that the RadGridView is bound to MyListA at design time.
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
 
        this.radGridView1.Columns.Last().DataTypeConverter = new MyConverter();
    }
 
    public class MyListA : List<A>
    {
        public MyListA()
        {
            for (int i = 0; i < 5; i++)
            {
                this.Add(new A(i,"Name" + i, new B(i,"Description" + i)));
            }
        }
    }
 
    public class MyListB : List<B>
    {
        public MyListB()
        {
            for (int i = 0; i < 5; i++)
            {
                this.Add(new B(i,"Description" + i));
            }
        }
    }
 
    public class A
    {
        public int Id { get; set; }
 
        public string Name { get; set; }
 
        public B Info { get; set; }
 
        public A(int id, string name, B info)
        {
            this.Id = id;
            this.Name = name;
            this.Info = info;
        }
    }
 
    public class B
    {
        public int UniqueIdentifier { get; set; }
 
        public string Description { get; set; }
 
        public B(int uniqueIdentifier, string description)
        {
            this.UniqueIdentifier = uniqueIdentifier;
            this.Description = description;
        }
    }
 
    B objB = null;
 
    private void radGridView1_EditorRequired(object sender, EditorRequiredEventArgs e)
    {
        if (this.radGridView1.CurrentColumn.Name == "Info")
        {
            RadDropDownListEditor editor = new RadDropDownListEditor();
            RadDropDownListEditorElement editorElement = editor.EditorElement as RadDropDownListEditorElement;
            editorElement.DataSource = new MyListB();
            editorElement.DisplayMember = "Description";
            editorElement.ValueMember = "UniqueIdentifier";
            e.Editor = editor;
        }
    }
 
    public class MyConverter : TypeConverter
    {
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                return true;
            }
            return base.CanConvertTo(context, destinationType);
        }
 
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType == typeof(string) && value is B)
            {
                return ((B)value).Description;
            }
            return base.ConvertTo(context, culture, value, destinationType);
        }
 
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            if (sourceType == typeof(int))
            {
                return true;
            }
            return base.CanConvertFrom(context, sourceType);
        }
 
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            GridDataCellElement cell = context as GridDataCellElement;
            if (value is int && cell != null)
            {
                if (cell.RowInfo.Tag != null)
                {
                    return cell.RowInfo.Tag;
                }
                return null;
            }
            return base.ConvertFrom(context, culture, value);
        }
    }
 
    private void radGridView1_CellEditorInitialized(object sender, GridViewCellEventArgs e)
    {
        RadDropDownListEditor editor = e.ActiveEditor as RadDropDownListEditor;
        if (editor != null)
        {
            RadDropDownListEditorElement editorElement = editor.EditorElement as RadDropDownListEditorElement;
            objB = this.radGridView1.CurrentCell.Value as B;
            if (objB != null)
            {
                editorElement.SelectedValue = objB.UniqueIdentifier;
                editorElement.SelectedIndexChanged -= editorElement_SelectedIndexChanged;
                editorElement.SelectedIndexChanged += editorElement_SelectedIndexChanged;
            }
        }
    }
 
    private void editorElement_SelectedIndexChanged(object sender, Telerik.WinControls.UI.Data.PositionChangedEventArgs e)
    {
        RadDropDownListEditorElement editorElement = sender as RadDropDownListEditorElement;
        if (e.Position > -1)
        {
            ((GridDataCellElement)editorElement.Parent).RowInfo.Tag = editorElement.SelectedItem.DataBoundItem as B;
        }
    }
}

I hope this information helps. Should you have further questions, I would be glad to help.

Regards,
Desislava
Telerik
 
Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
 
Tags
GridView
Asked by
Paul
Top achievements
Rank 1
Answers by
Dess | Tech Support Engineer, Principal
Telerik team
Share this question
or