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

Change cells custom control based on value from a columns dropdown

25 Answers 975 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Svein Thomas
Top achievements
Rank 1
Svein Thomas asked on 08 Nov 2010, 01:44 PM
Hi,

In my grid i have two columns. The first column are binded to a list of custom datatypes. 
A custom datatype can be: DataTime, number or list of strings.
The second column should be of the type that the first column selected value is on the same row.

So if the selected value in the first column is DateTime, then the second column (ON THIS ROW) should show a DataTimePicker. 
If the selected value in the first column is a "list of strings", then i have to lookup the value in the database and present the second column (ON THE SAME ROW) with a list of strings in a combobox and so on.

1. Is there any way to do this?
2. How do i get the bounded item from the combobox in the first column?

/ST

25 Answers, 1 is accepted

Sort by
0
Richard Slade
Top achievements
Rank 2
answered on 08 Nov 2010, 02:01 PM
Hi,

Something similar has come up recently. Have a look at this forum post.
Let me know if this helps or if you need more information
richard
0
Svein Thomas
Top achievements
Rank 1
answered on 08 Nov 2010, 02:12 PM
Hi and thanks for a quick answer.

Well this is not exactly the same. Cause this make use of only combobox's in both columns.
What i want is to change the type of the control within the cell in the second column based on the value of the first combobox. 

/ST
0
Emanuel Varga
Top achievements
Rank 1
answered on 08 Nov 2010, 06:00 PM
Hello Svein,

You cannot change the type of the column like that but you can use custom editors based on a condition, please take a look at this thread.

If you will follow the example project and my suggestions from that thread everything should work fine.

Hope this helps, if you have any other questions or comments, please let me know,

Best Regards,
Emanuel Varga
0
Svein Thomas
Top achievements
Rank 1
answered on 08 Nov 2010, 11:27 PM
Hi Emanuel,

This one helped me alot :) Thanks.. 

Its now narrowed down to one very critical question :)

How can i get datasource value (databounditem) from the first columns combobox?

The combobox  here is bounded to a datatable. And based on values in this table i deside what to show in the second column. 
Right now im only able to get the value in the valuemember. 
The RadDropDownList do have DataBoundItem, how can i find this in the combobox. 

Regards
Svein Thomas
0
Emanuel Varga
Top achievements
Rank 1
answered on 08 Nov 2010, 11:33 PM
Hello again,

This one is very easy, you can access it using the radGridView1.Rows[e.RowIndex].Cells["ColumnName"].Value, or directly the data bound item, like radGridView1.Rows[e.RowIndex].DataBoundItem.

Glad to be able to help,

If you have any more questions please just let me know, and if the question has been solved, please mark the question as answered, so that others can find the answers to their questions faster.

Best Regards,
Emanuel Varga
0
Svein Thomas
Top achievements
Rank 1
answered on 08 Nov 2010, 11:46 PM
Hi again,

Yes but that gives me only the value of the Combobox.ValueMember.
What I want is to get the object behind. Not on rowlevel, but on cell level (the combobox within the cell).

Regards
Svein Thomas
0
Emanuel Varga
Top achievements
Rank 1
answered on 08 Nov 2010, 11:53 PM
Hello again,

There is no way of getting that like this, but you can use Linq to do this, something like this:
var columnDataSource = ((GridViewComboBoxColumn)radGridView1.Columns[e.ColumnIndex]).DataSource as List<CustomObject>;
var selectedItem = columnDataSource.Where(o => o.Id == radGridView1.Rows[e.RowIndex].Cells["Column"].Value).FirstOrDefault();

Hope you understood, so basically you can just get that item from the data source for the column for that id.

Hope this helps, if you have any other questions or comments, please let me know,

Best Regards,
Emanuel Varga
0
Svein Thomas
Top achievements
Rank 1
answered on 09 Nov 2010, 09:35 AM
Since Q2 2010 SP2, Telerik says that they are using RadDropDownList instead of the RadCombobox in the ComboboxColumn type.
I think it's strange that i'm not able to access the databounditem of the RadDropDownList when I have chosen my value.

And now over to my second problem with this solution.

I have created a class that inherits from RadDropDownListEditor.
This class overrides BeginEdit and Value.
BeginValue looks like this:

public override void BeginEdit()
{
    RadDropDownListEditorElement editorElement = ((RadDropDownListEditorElement)this.EditorElement);
 
    var DataSource = _db.TCs.Where(tc => tc.TC_GROUP_MEMBERs.Any(tcg => tcg.TC_GROUP.LAND_IDX == 578));
    editorElement.DataSource = DataSource;
    editorElement.DisplayMember = "TC1";
    editorElement.ValueMember = "ID"; ;
 
    base.BeginEdit();
}

And in my form i access the EditorRequired event like this:
void radGridView1_EditorRequired(object sender, EditorRequiredEventArgs e)
{
    if (this.radGridView1.Columns[0].IsCurrent && e.EditorType.Name == "RadTextBoxEditor")
    {
        //e.Editor = new TCDropDownListEditor();
        e.EditorType = typeof(TCDropDownListEditor);
    }
}

Now.. First time I access the cell the dropdown shows like it should with all the items. 
Second time i access cell, the text disappears and the list is empty.

If I remove the comment on the: 
void radGridView1_EditorRequired(object sender, EditorRequiredEventArgs e)
{
    if (this.radGridView1.Columns[0].IsCurrent && e.EditorType.Name == "RadTextBoxEditor")
    {
        e.Editor = new TCDropDownListEditor();
        e.EditorType = typeof(TCDropDownListEditor);
    }
}
The list shows, but the cell value is the first item in list, not the one that i chose previously.

So i figured out that the e.Editor (the editor that is created) is the one that i need to get and set in this event.
I think its strange, and maybe a bug that the e.Editor does not get set when accessing this cell the first time.
Each time i enter this EditorRequired event, the e.Editor is null.

Any good ideas on how to solve this one?

/ST

0
Emanuel Varga
Top achievements
Rank 1
answered on 09 Nov 2010, 09:39 AM
Hello again,

Yes, don't use the EditorRequired event to set the new data source for the dropdownlist, please use the CellEditorInitialized event, do do this.

Hope this helps, if you have any other questions or comments, please let me know,

Best Regards,
Emanuel Varga
0
Svein Thomas
Top achievements
Rank 1
answered on 09 Nov 2010, 09:58 AM
Well, i still have to this in the EditorRequire event?
e.EditorType = typeof(TCDropDownListEditor);

I see that the sender object in the CellEditorInitialized have the ActiveEditor, but this does not help me much if the editor is set iin the EditorRequired event and the editor there is null?

/ST

0
Emanuel Varga
Top achievements
Rank 1
answered on 09 Nov 2010, 10:16 AM
Hello again,

Yes, you still have to specify the type in the EditorRequired event, but for the DataSource you have to wait for the CellEditorInitialized event.
It should be like this:
void radGridView1_EditorRequired(object sender, EditorRequiredEventArgs e)
{
    if (this.radGridView1.Columns[0].IsCurrent && e.EditorType.Name == "RadTextBoxEditor")
    {
        e.Editor = new TCDropDownListEditor();
        e.EditorType = typeof(TCDropDownListEditor);
    }
}
and after that you can do something like this:
void radGridView1_CellEditorInitialized(object sender, GridViewCellEventArgs e)
{
    var editManager = sender as GridViewEditManager;
    var editor = editManager as TCDropDownListEditor;
    if (editor != null)
    {
       //take the editor element here and set the data source
    }
}

Hope this helps, if you have any other questions or comments, please let me know,

Best Regards,
Emanuel Varga
0
Svein Thomas
Top achievements
Rank 1
answered on 09 Nov 2010, 10:28 AM
Well, as i tried to say in my last post, this will not help me since we create a new editor each time we access the cell.
I would like to store the editor used in the cell and access the same editor each time i edit the current cell.

So my solution would be to create a collection of editors. I cannot see that RadGridView already have this type of collection, or do it?

PS: Emanuel, thanks alot for your help ;)

/ST
0
Emanuel Varga
Top achievements
Rank 1
answered on 09 Nov 2010, 10:33 AM
Hello again,

This is the default behavior of the grid, it always creates a new editor element based on the type supplied, so please just leave it like this and tell me if it works.
Or you can just try leaving just the type there, but the grid will create a new editor using reflection, internally.

Hope this helps, if you have any other questions or comments, please let me know,

Best Regards,
Emanuel Varga
0
Svein Thomas
Top achievements
Rank 1
answered on 09 Nov 2010, 10:43 AM
But when I open a Dropdown box, i expect it to position on the selected item in the dropdownbox, not at the top. 
This is the default behavior of a standard dropdown box. I cannot make this work. 
Everytime i go into the cell and open the dropdown it starts on the top. And i understand that it does, since I always creates a new editor (read: combobox) with values each time I enter the cell. 
I mean that the e.Editor property of the RequiredEditor event should be set to the editor it was previously (the grid should remember this).

I have to create a workaround to make this work as i expect, if you cannot point me in the right direction here?

/ST
0
Emanuel Varga
Top achievements
Rank 1
answered on 09 Nov 2010, 10:48 AM
Hello,

No, this is not because it always creates a new dropdown this usually happens when the dropdown does not find a match for the value member.

If you can post a very small test application i will be more than happy to help you find the problem, but like this it is very hard, especially because you are using a custom edit control...

Best Regards,
Emanuel Varga
0
Svein Thomas
Top achievements
Rank 1
answered on 09 Nov 2010, 11:20 AM
Sorry Emanuel, you are correct.. this was caused by the return value of the custom editor. 
One other thing. The dropdown's valuemember is shown in the grid, not the display member.. do you know why?

/ST
0
Svein Thomas
Top achievements
Rank 1
answered on 09 Nov 2010, 12:25 PM
Hi again Emanuel,

Have one more question for you. This grids allow me to add a new row. But when i do i get a strange errormessage: DataItem not contain "column1" property name.

How can i attach my project? I can only attach gif, jpg or .png.

 /ST
0
Svein Thomas
Top achievements
Rank 1
answered on 09 Nov 2010, 12:50 PM
Hi again, 
I solved the latest problem. that was some code in the designer.cs file created by the property builder.

But one last question for you ;)

See the attached pictures.

when i have a list like this with 4 different rows.. and i go back to row number one and click in the first cell, the text given in the dropdown then is the last that i added, (the one from the last row "teststring[]")

This happends if i click in any of the first column cells. the teststring[] are not the first in the list. It seems like it remembers the last selected one (in any of the cells in that column)

Any idea on how to get around this problem?

Here is the forms code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Telerik.WinControls.UI;
using Telerik.WinControls;
 
namespace WindowsFormsApplication2
{
    public partial class Form2 : Form
    {
        BindingList<TextCode> TextCodes = new BindingList<TextCode>();
 
        public Form2()
        {
            InitializeComponent();
            Init();
        }
 
        public void Init()
        {
            var t = new TextCode(1, "TestString", TextCodeTypeEnum._string);
            var t1 = new TextCode(2, "TestNumber", TextCodeTypeEnum._number);
            var t2 = new TextCode(3, "TestDatetime", TextCodeTypeEnum._datetime);
            var t3 = new TextCode(4, "TestString[]", TextCodeTypeEnum._string);
 
            t3.TextCodeValueList = new List<TextCodeValue>() {  new TextCodeValue(1, "Test string1"),
                                                                new TextCodeValue(2, "Test string2"),
                                                                new TextCodeValue(3, "Test string3")};
 
            TextCodes.Add(t);
            TextCodes.Add(t1);
            TextCodes.Add(t2);
            TextCodes.Add(t3);
 
 
            radGridView1.AutoGenerateColumns = false;
            radGridView1.EditorRequired += new Telerik.WinControls.UI.EditorRequiredEventHandler(radGridView1_EditorRequired);
            radGridView1.CellEditorInitialized += new Telerik.WinControls.UI.GridViewCellEventHandler(radGridView1_CellEditorInitialized);
             
 
        }
 
        void radGridView1_CellEditorInitialized(object sender, Telerik.WinControls.UI.GridViewCellEventArgs e)
        {
            var editManager = sender as GridViewEditManager;
            var editor = editManager.ActiveEditor as RadDropDownListEditor;
             
            if (editor== null) return;
 
            var editorElement = ((RadDropDownListEditor)editor).EditorElement;
            switch (e.ColumnIndex)
            {
                case 0:
                         
                    ((RadDropDownListEditorElement)editorElement).DataSource = TextCodes;
                    ((RadDropDownListEditorElement)editorElement).DisplayMember = "Name";
                    ((RadDropDownListEditorElement)editorElement).ValueMember = "Name"; ;
                    break;
                case 1:
 
 
                    ((RadDropDownListEditorElement)editorElement).DataSource = TextCodes.SingleOrDefault(t => t.Name == this.radGridView1.CurrentRow.Cells[0].Value).TextCodeValueList;
                    ((RadDropDownListEditorElement)editorElement).DisplayMember = "Value";
                    ((RadDropDownListEditorElement)editorElement).ValueMember = "Value"; ;
 
                    break;
            }
        }
 
        void radGridView1_EditorRequired(object sender, Telerik.WinControls.UI.EditorRequiredEventArgs e)
        {
            if (this.radGridView1.Columns[0].IsCurrent && e.EditorType.Name == "RadTextBoxEditor")
            {
                e.Editor = new RadDropDownListEditor();
                e.EditorType = typeof(RadDropDownListEditor);
 
 
            }
            else if (this.radGridView1.Columns[1].IsCurrent)
            {
                var a = TextCodes.SingleOrDefault(t => t.Name == this.radGridView1.CurrentRow.Cells[0].Value);
                if (a == null) return;
                if (a.TextCodeType == TextCodeTypeEnum._datetime)
                {
                    e.Editor = new RadDateTimeEditor();
                    e.EditorType = typeof(RadDateTimeEditor);
                }
                else if(a.TextCodeType == TextCodeTypeEnum._string && a.TextCodeValueList==null)
                {
                    e.Editor = new RadTextBoxEditor();
                    e.EditorType = typeof(RadTextBoxEditor);
                }
                else if(a.TextCodeType == TextCodeTypeEnum._string && a.TextCodeValueList!=null)
                {
                    e.Editor = new RadDropDownListEditor();
                    e.EditorType = typeof(RadDropDownListEditor);
                }
                else if(a.TextCodeType == TextCodeTypeEnum._number)
                {
                    e.Editor = new GridSpinEditor();
                    e.EditorType = typeof(GridSpinEditor);
                }
            }
        }
 
 
 
 
    }
}

And here is the supporting classes:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace WindowsFormsApplication2
{
    public enum TextCodeTypeEnum
    {
        _string=1,
        _number=2,
        _datetime=4
    }
 
    public class TextCode
    {
        public TextCode(int id, string name, TextCodeTypeEnum textCodeType)
        {
            ID = id;
            Name = name;
            TextCodeType = textCodeType;
        }
 
        public int ID { get; set; }
        public string Name { get; set; }
        public TextCodeTypeEnum TextCodeType{get;set;}
        public List<TextCodeValue> TextCodeValueList { get; set; }
 
    }
 
 
    public class TextCodeValue
    {
        public TextCodeValue(int id, string value)
        {
            ID = id;
            Value = value;
        }
        public int ID { get; set; }
        public string Value { get; set; }
    }
 
}
0
Accepted
Emanuel Varga
Top achievements
Rank 1
answered on 09 Nov 2010, 02:24 PM
Hello,

Please try the following:
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;
using Telerik.WinControls.UI;
 
public partial class Form1 : Form
{
    BindingList<TextCode> TextCodes = new BindingList<TextCode>();
 
    private RadGridView radGridView1;
 
    public Form1()
    {
        InitializeComponent();
        this.Controls.Add(radGridView1 = new RadGridView());
        radGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
        radGridView1.Dock = DockStyle.Fill;
        radGridView1.AllowAddNewRow = true;
 
        var comboBoxColumn = new GridViewComboBoxColumn("TextCode");
        comboBoxColumn.DataSource = TextCodes;
        comboBoxColumn.DisplayMember = "Name";
        comboBoxColumn.ValueMember = "Name";
        radGridView1.Columns.Add(comboBoxColumn);
        radGridView1.Columns.Add(new GridViewTextBoxColumn("TextCodeValue"));
 
        radGridView1.Columns[0].FieldName = "Name";
 
        Init();
    }
 
    public void Init()
    {
        var t = new TextCode(1, "TestString", TextCodeTypeEnum._string);
        var t1 = new TextCode(2, "TestNumber", TextCodeTypeEnum._number);
        var t2 = new TextCode(3, "TestDatetime", TextCodeTypeEnum._datetime);
        var t3 = new TextCode(4, "TestString[]", TextCodeTypeEnum._string);
 
        t3.TextCodeValueList = new List<TextCodeValue>() {  new TextCodeValue(1, "Test string1"),
                                                            new TextCodeValue(2, "Test string2"),
                                                            new TextCodeValue(3, "Test string3")};
 
        TextCodes.Add(t);
        TextCodes.Add(t1);
        TextCodes.Add(t2);
        TextCodes.Add(t3);
 
        radGridView1.DataSource = TextCodes;
        radGridView1.AutoGenerateColumns = false;
        radGridView1.EditorRequired += new Telerik.WinControls.UI.EditorRequiredEventHandler(radGridView1_EditorRequired);
        radGridView1.CellEditorInitialized += new Telerik.WinControls.UI.GridViewCellEventHandler(radGridView1_CellEditorInitialized);
    }
 
    void radGridView1_CellEditorInitialized(object sender, Telerik.WinControls.UI.GridViewCellEventArgs e)
    {
        var editManager = sender as GridViewEditManager;
        var editor = editManager.ActiveEditor as RadDropDownListEditor;
 
        if (editor == null || e.ColumnIndex != 1)
            return;
 
        var editorElement = ((RadDropDownListEditor)editor).EditorElement as RadDropDownListEditorElement;
 
        editorElement.DataSource = TextCodes.SingleOrDefault(t => t.Name.Equals(this.radGridView1.CurrentRow.Cells[0].Value)).TextCodeValueList;
        editorElement.DisplayMember = "Value";
        editorElement.ValueMember = "Value";
 
        if (this.radGridView1.CurrentRow.Cells[1].Value == null)
        {
            this.radGridView1.CurrentRow.Cells[1].Value = editorElement.SelectedValue;
        }
        else
        {
            editorElement.SelectedValue = this.radGridView1.CurrentRow.Cells[1].Value;
        }
    }
 
    void radGridView1_EditorRequired(object sender, Telerik.WinControls.UI.EditorRequiredEventArgs e)
    {
        if (this.radGridView1.Columns[1].IsCurrent)
        {
            var a = TextCodes.SingleOrDefault(t => t.Name.Equals(this.radGridView1.CurrentRow.Cells[0].Value));
            if (a == null)
                return;
            if (a.TextCodeType == TextCodeTypeEnum._datetime)
            {
                e.Editor = new RadDateTimeEditor();
                e.EditorType = typeof(RadDateTimeEditor);
            }
            else if (a.TextCodeType == TextCodeTypeEnum._string && a.TextCodeValueList == null)
            {
                e.Editor = new RadTextBoxEditor();
                e.EditorType = typeof(RadTextBoxEditor);
            }
            else if (a.TextCodeType == TextCodeTypeEnum._string && a.TextCodeValueList != null)
            {
                e.Editor = new RadDropDownListEditor();
                try
                {
                    ((RadDropDownListEditor)e.Editor).DropDownStyle = Telerik.WinControls.RadDropDownStyle.DropDownList;
                }
                catch (System.Exception)
                {
                }
                e.EditorType = typeof(RadDropDownListEditor);
            }
            else if (a.TextCodeType == TextCodeTypeEnum._number)
            {
                e.Editor = new GridSpinEditor();
                e.EditorType = typeof(GridSpinEditor);
            }
        }
    }
}
 
public enum TextCodeTypeEnum
{
    _string = 1,
    _number = 2,
    _datetime = 4
}
 
public class TextCode
{
    public TextCode(int id, string name, TextCodeTypeEnum textCodeType)
    {
        ID = id;
        Name = name;
        TextCodeType = textCodeType;
    }
 
    public int ID
    {
        get;
        set;
    }
 
    public string Name
    {
        get;
        set;
    }
 
    public TextCodeTypeEnum TextCodeType
    {
        get;
        set;
    }
 
    public List<TextCodeValue> TextCodeValueList
    {
        get;
        set;
    }
}
 
public class TextCodeValue
{
    public TextCodeValue(int id, string value)
    {
        ID = id;
        Value = value;
    }
 
    public int ID
    {
        get;
        set;
    }
 
    public string Value
    {
        get;
        set;
    }
}

Hope this helps, if you have any other questions or comments, please let me know,

Best Regards,
Emanuel Varga
0
Svein Thomas
Top achievements
Rank 1
answered on 09 Nov 2010, 02:35 PM
Thanks a lot.. 
One other thing: why is the valuemember presented when i'm exiting the cell and not the displaymember?
Is there a way to solve this? without having to set the Valuemenber property to the same as the displaymember?

And again, isn't there any way to get the DataBoundItem from the dropdownlist?

And a final thing: How can i set a default value into the dropdownlist. Lets say i select the "teststrings[]" and want the list in the column two to default show "test string3" when i enter the cell?

/ST
0
Emanuel Varga
Top achievements
Rank 1
answered on 09 Nov 2010, 02:44 PM
Hello,

Because you are using a GridViewTextBoxColumn, you can only show the Value from that cell, and the value is the one from the DropDown's value member.

Where do you want to get the dropdown's data bound item? While editing you can, like so:
editorElement.SelectedItem.DataBoundItem

Because once the edit for the cell has ended, the dropdown has been disposed.

Hope this helps, if you have any other questions or comments, please let me know,

Best Regards,
Emanuel Varga
0
Svein Thomas
Top achievements
Rank 1
answered on 09 Nov 2010, 02:47 PM
Don't know if you saw my last update of the last post:

And a final thing: How can i set a default value into the dropdownlist. Lets say i select the "teststrings[]" and want the list in the column two to default show "test string3" when i enter the cell?

Do you know the answer to this as well?

ST
0
Accepted
Emanuel Varga
Top achievements
Rank 1
answered on 09 Nov 2010, 03:16 PM
Hello again,

Don't know if you saw the changes i've made to your code ;)

if (this.radGridView1.CurrentRow.Cells[1].Value == null)
{
    this.radGridView1.CurrentRow.Cells[1].Value = editorElement.SelectedValue;
}
else
{
    editorElement.SelectedValue = this.radGridView1.CurrentRow.Cells[1].Value;
}

You can move this line, or put it in the first if with the default selected value, something like this:

if (this.radGridView1.CurrentRow.Cells[1].Value == null)
{
    editorElement.SelectedValue = "test string3";
    this.radGridView1.CurrentRow.Cells[1].Value = editorElement.SelectedValue;
}
else
{
    editorElement.SelectedValue = this.radGridView1.CurrentRow.Cells[1].Value;
}

Hope this helps, if you have any other questions or comments, please let me know,

Best Regards,
Emanuel Varga
0
Emanuel Varga
Top achievements
Rank 1
answered on 11 Nov 2010, 10:21 AM
Hello again Svein,

Just wanted to follow up and ask if your problem has been solved.

If you have any more questions please just let me know, and if the question has been solved, please mark the all of the helpfull posts as answers, so that others can find the answers to their questions faster.

Best Regards,
Emanuel Varga
WinForms MVP
0
Svein Thomas
Top achievements
Rank 1
answered on 11 Nov 2010, 10:34 AM
Hi again,

Problems solved! 
thanks..

/ST
Tags
GridView
Asked by
Svein Thomas
Top achievements
Rank 1
Answers by
Richard Slade
Top achievements
Rank 2
Svein Thomas
Top achievements
Rank 1
Emanuel Varga
Top achievements
Rank 1
Share this question
or