Custom editor

1 Answer 37 Views
GridView
Carl
Top achievements
Rank 1
Iron
Iron
Iron
Carl asked on 05 Jul 2024, 05:29 PM

I have a data entry RadGridView bound to a collection of POCOs. It has some rather compiles editing requirements. On one particular row, there is a cell that requires the edit control to be a multi-selection combo box. On all other rows it requires a numeric entry. I created the column as a GridViewComboBoxColumn. and then tried to create a custom control to replace the standard editor using the EditorRequired event like this:

        private void gvMatrix_EditorRequired(object sender, EditorRequiredEventArgs e)

        {
            if (gvMatrix.CurrentRow.Cells["Comparison"].Value.ToString() == "One of")
            {
                if (e.EditorType == typeof(CustomCheckedListBox))
                    e.EditorType = typeof(CustomCheckedListBox);
            }

//Otherwise I need numeric entry

        }

 

Then, I tried to create the custom control based on the example on the Telerik site (https://docs.telerik.com/devtools/winforms/controls/gridview/editors/using-custom-editors) and came up with this:

 public class CustomCheckedListBox : BaseGridEditor
 {
     protected override RadElement CreateEditorElement()
     {
         return new CustomCheckedListBoxElement();
     }

     public override object Value
     {
         get
         {
             CustomCheckedListBoxElement element = this.EditorElement as CustomCheckedListBoxElement;
             return element.CheckedDropDownElement.Value;
         }
         set
         {
             CustomCheckedListBoxElement element = this.EditorElement as CustomCheckedListBoxElement;
             element.CheckedDropDownElement.Value = value;
         }
     }

     public override void BeginEdit()
     {
         base.BeginEdit();

         CustomCheckedListBoxElement element = this.EditorElement as CustomCheckedListBoxElement;

         var statesData = new List<Dictionary>();

         statesData.Add(new Dictionary { DictionaryKeyString = "AK", Description = "Alaska" });
         statesData.Add(new Dictionary { DictionaryKeyString = "NJ", Description = "New Jersey" });
         statesData.Add(new Dictionary { DictionaryKeyString = "AL", Description = "Alabama" });
         statesData.Add(new Dictionary { DictionaryKeyString = "GA", Description = "Georgia" });

         element.DataSource = statesData;
         element.DropDownStyle = RadDropDownStyle.DropDownList;
         element.ValueMember = "DictionaryKeyString";
         element.DisplayMember = "Description";
     }

     public override bool EndEdit()
     {
         return base.EndEdit();
     }

     //public string? ValueMember { get; set; }
     //public string? DisplayMember { get; set; }
     //public object? DataSource { get; set; }
 }

 public class CustomCheckedListBoxElement : RadCheckedDropDownListElement
 {
     RadCheckedDropDownListElement dropDownListElement = new RadCheckedDropDownListElement();

     public CustomCheckedListBoxElement()
     {
     }

     public RadCheckedDropDownListElement CheckedDropDownElement
     {
         get =>  this.dropDownListElement;           
     }

     protected override void CreateChildElements()
     {
         base.CreateChildElements();
     }
 }

What I get is a an empty dropdown in the cell with no data appearing. Ideally I'd like to instantiate the custom control and pass in the DataSource, ValueMember, etc. so I can reuse it elsewhere. The goal is to retrieve a list of selected states and display them like this when the cell is not in edit mode:

Alabama

New Jersey

Georgia

Any ideas on how to accomplish this?

Thanks

Carl

1 Answer, 1 is accepted

Sort by
0
Dinko | Tech Support Engineer
Telerik team
answered on 10 Jul 2024, 09:26 AM

Hi Carl,

The provided code snippet is greatly shared.

I will start with the EditorRequired event handler. I would suggest checking the nested if clause. By default the first time you enter in edit mode, the editor type won't be CustomCheckedListBox and the custom editor won't be changed. Probably this needs to be refactored. 

private void gvMatrix_EditorRequired(object sender, EditorRequiredEventArgs e)
{
    if (radGridView1.CurrentRow.Cells["Name"].Value.ToString() == "One of")
    { // refactored
        e.EditorType = typeof(CustomCheckedListBox);
    }
}

As for the custom editor. The CustomCheckedListBoxElement exposes an additional RadCheckedDropDownListElement field inside it. I am not familiar with your requirements, but I think that this is not required. You can remove it and use the custom class instead as it derives from RadCheckedDropDownListElement. 

public class CustomCheckedListBoxElement : RadCheckedDropDownListElement
{
    public CustomCheckedListBoxElement()
    {
    }
}

Then you can populate it in the BeginEdit() method and use the SelectedValue property of the CustomCheckedListBoxElement to set the Value of the cell.

public class CustomCheckedListBox : BaseGridEditor
{
    protected override RadElement CreateEditorElement()
    {
        return new CustomCheckedListBoxElement();
    }

    public override object Value
    {
        get
        {
            CustomCheckedListBoxElement element = this.EditorElement as CustomCheckedListBoxElement;
            return element.SelectedValue;
        }
        set
        {
            CustomCheckedListBoxElement element = this.EditorElement as CustomCheckedListBoxElement;
            element.SelectedValue = value;
        }
    }

    public override void BeginEdit()
    {
        base.BeginEdit();

        CustomCheckedListBoxElement element = this.EditorElement as CustomCheckedListBoxElement;
        var statesData = new List<Dictionary>();

        statesData.Add(new Dictionary { DictionaryKeyString = "AK", Description = "Alaska" });
        statesData.Add(new Dictionary { DictionaryKeyString = "NJ", Description = "New Jersey" });
        statesData.Add(new Dictionary { DictionaryKeyString = "AL", Description = "Alabama" });
        statesData.Add(new Dictionary { DictionaryKeyString = "GA", Description = "Georgia" });

        element.DataSource = statesData;
        element.DropDownStyle = RadDropDownStyle.DropDownList;
        element.ValueMember = "DictionaryKeyString";
        element.DisplayMember = "Description";

    }

    public override bool EndEdit()
    {
        return base.EndEdit();
    }

    //public string? ValueMember { get; set; }
    //public string? DisplayMember { get; set; }
    //public object? DataSource { get; set; }
}

Keep in mind that when the user clicks on a cell with the text "One of", this string will try to be set as a text to the custom editor. However, such a string does not exist in the dropdown list and it will be ignored. This is just a note which I think you need to take into account.

I hope that I was able to help you.

Regards,
Dinko | Tech Support Engineer
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

Carl
Top achievements
Rank 1
Iron
Iron
Iron
commented on 11 Jul 2024, 12:34 PM

Thanks and we're getting close but not there yet.

 

Here's what I have now:

        private void gvMatrix_EditorRequired(object sender, EditorRequiredEventArgs e)
        {
            if (gvMatrix.CurrentColumn.Name == "ComparisonValue" && gvMatrix.CurrentRow.Cells["Comparison"].Value.ToString() == "One of")
                e.EditorType = typeof(CustomCheckedListBox);
        }

 

and here is the modified class:

 

using Telerik.WinControls;
using Telerik.WinControls.UI;
using VisionDataAndServices.CommonModels;

namespace VisionUI.Setup
{
    public class CustomCheckedListBox : BaseGridEditor
    {
        protected override RadElement CreateEditorElement()
        {
            return new CustomCheckedListBoxElement();
        }

        public override object Value
        {
            get
            {
                CustomCheckedListBoxElement element = this.EditorElement as CustomCheckedListBoxElement;
                return string.Join("\r\n", element.CheckedItems);
            }
            set
            {
                CustomCheckedListBoxElement element = this.EditorElement as CustomCheckedListBoxElement;

                LoadStateData(element);

                element.CheckedDropDownElement.SelectedValue = value;
            }
        }

        public override void BeginEdit()
        {
            base.BeginEdit();

            CustomCheckedListBoxElement element = this.EditorElement as CustomCheckedListBoxElement;

            LoadStateData(element);
        }

        private void LoadStateData(CustomCheckedListBoxElement element)
        {
            var statesData = new List<Dictionary>();

            statesData.Add(new Dictionary { DictionaryKeyString = "AK", Description = "Alaska" });
            statesData.Add(new Dictionary { DictionaryKeyString = "NJ", Description = "New Jersey" });
            statesData.Add(new Dictionary { DictionaryKeyString = "AL", Description = "Alabama" });
            statesData.Add(new Dictionary { DictionaryKeyString = "GA", Description = "Georgia" });

            element.DataSource = statesData;
            element.DropDownStyle = RadDropDownStyle.DropDownList;
            element.ValueMember = "DictionaryKeyString";
            element.DisplayMember = "Description";
        }

        public override bool EndEdit()
        {
            return base.EndEdit();
        }

        //public string? ValueMember { get; set; }
        //public string? DisplayMember { get; set; }
        //public object? DataSource { get; set; }
    }

    public class CustomCheckedListBoxElement : RadCheckedDropDownListElement
    {
        RadCheckedDropDownListElement dropDownListElement = new RadCheckedDropDownListElement();

        public CustomCheckedListBoxElement()
        {
        }

        public RadCheckedDropDownListElement CheckedDropDownElement
        {
            get =>  this.dropDownListElement;           
        }

        protected override void CreateChildElements()
        {
            base.CreateChildElements();
        }
    }

}

When I edit I get this, which is correct:

When I finished editing I get this, which is also correct:

If I try to edit again, I should get the same dropdown options as shown in the first image but with Alaska and New Jersey checked. However, nthing shows in the drop-down. The setter correctly contains a value of Alaska,New Jersey but BEginEdit does not file and the DataSource is not reloaded.

What am I doing wrong?

Thanks

Carl

Dinko | Tech Support Engineer
Telerik team
commented on 15 Jul 2024, 06:53 AM

When multiple items in the RadCheckedDropDownListElement control are selected, they will separate by its default operator which is ";". You need to take this into account when you want to preserve the selected items by the end user. Upon trying a few approaches, I think I found a better and more clear one. Instead of applying a custom editor type, you can directly apply the Editor itself. It is a more simple way of achieving the same scenario.

rivate void RadGridView1_EditorRequired(object sender, Telerik.WinControls.UI.EditorRequiredEventArgs e)
{
    if (radGridView1.CurrentColumn.Name == "Name") // your custom check here
    {
        RadCheckedDropDownListElement editor = new GridViewCheckedDropDownListEditor();                
        editor.DataSource = this.dictionaries;
        editor.DisplayMember = "Description";
        e.Editor = editor;
    }                
}  


public class GridViewCheckedDropDownListEditor : RadCheckedDropDownListElement
{
    public override object Value
    {
        get
        {
            return this.Text;
        }
        set
        {
            this.Text = value.ToString();
        }
    }
}

Here is how it looks when the user selects multiple values.

You will need to keep the same method and pass it to the Value property of the RadCheckedDropDownListElement to select again the same items. I am also attaching my test project. I hope that this approach will work.

Carl
Top achievements
Rank 1
Iron
Iron
Iron
commented on 15 Jul 2024, 10:35 AM

Dinko

Thanks but I don't see the test project attached

Carl

Dinko | Tech Support Engineer
Telerik team
commented on 15 Jul 2024, 10:43 AM

It seems that the project failed to attach. Accept my apologies for that. I am re-attaching it again.
Carl
Top achievements
Rank 1
Iron
Iron
Iron
commented on 17 Jul 2024, 12:49 AM

Dinko

Thanks, this works great.

One final question from our UI designer: Can the cell always show the dropdown arrow so the user knows that there is a dropdown there?

Thanks

Carl

Dinko | Tech Support Engineer
Telerik team
commented on 17 Jul 2024, 08:17 AM

In that case, you will have to implement a permanent editor. A sample solution is demonstrated in the Permanent editor in a filter cell KB article. The KB shows how to add a permanent editor to a filter cell. You can try it use the same approach for a data cell. You can also check the How to Create Custom Cells with Input Elements KB article which also demonstrates a similar approach for data cells. I hope that these articles will help you to implement your requirement.
Tags
GridView
Asked by
Carl
Top achievements
Rank 1
Iron
Iron
Iron
Answers by
Dinko | Tech Support Engineer
Telerik team
Share this question
or