Using custom editor in RadGridView

3 Answers 93 Views
GridView
Carl
Top achievements
Rank 1
Iron
Iron
Iron
Carl asked on 22 Aug 2023, 07:44 PM

I have some data driven edit fields that I need to edit based on the ControlType enum value in the event handler shown below. Mostly its working, but i have a few questions:

1. Note the commented code in DateEntry. I'd like to customize the date editor as I'm doing this using a DateTimePicker elsewhere in the application. How can I access the properties show in this code?

2. Is there an equivalent of a CheckBox or will I need to use a Yes/no combo box?

Thanks

Carl

        void gvDataDriven_EditorRequired(object sender, EditorRequiredEventArgs e)
        {
            int dataDrivenSetupID = int.Parse(gvDataDriven.CurrentRow.Cells["DataDrivenSetupID"].Value.ToString());

            DataDrivenSetup dataDrivenSetup = dataDrivenSetupList.Where(n => n.DataDrivenSetupID == dataDrivenSetupID).FirstOrDefault();

            switch ((ControlType)dataDrivenSetup.ControlID)
            {
                case ControlType.TextBox:

                    VirtualGridTextBoxEditor virtualGridTextBoxEditor = new VirtualGridTextBoxEditor();
                    virtualGridTextBoxEditor.MaxLength = dataDrivenSetup.MaxLength.Value;
                    e.Editor = virtualGridTextBoxEditor;
                    break;

                case ControlType.NumericEntry:
                    VirtualGridMaskedEditBoxEditor virtualGridMaskedEditBoxEditor = new VirtualGridMaskedEditBoxEditor();
                    virtualGridMaskedEditBoxEditor.MaskTextBox.MaskType = MaskType.Standard;
                    virtualGridMaskedEditBoxEditor.MaskTextBox.Mask = "000000.00";
                    virtualGridMaskedEditBoxEditor.MaskTextBox.TextAlign = HorizontalAlignment.Right;
                    virtualGridMaskedEditBoxEditor.MaskTextBox.TextMaskFormat = MaskFormat.ExcludePromptAndLiterals;
                    e.Editor = virtualGridMaskedEditBoxEditor;
                    break;

                case ControlType.DateEntry:
                    VirtualGridDateTimeEditor virtualGridDateTimeEditor = new VirtualGridDateTimeEditor();
                    //virtualGridDateTimeEditor.NullText = "MM/DD/YYYY";
                    //virtualGridDateTimeEditor.NullableValue = null;
                    //virtualGridDateTimeEditor.SetToNullValue();
                    //virtualGridDateTimeEditor.Format = DateTimePickerFormat.Short;
                    //virtualGridDateTimeEditor.DateTimePickerElement.TextBoxElement.MaskType = MaskType.FreeFormDateTime;

                    e.Editor = virtualGridDateTimeEditor;
                    break;

                case ControlType.CheckBox:
                    break;

                case ControlType.ComboBox:
                    VirtualGridDropDownListEditor dropDownListEditor = new VirtualGridDropDownListEditor();
                    RadDropDownListEditorElement element = dropDownListEditor.EditorElement as RadDropDownListEditorElement;
                    List<Dictionary> data = CommonServices.GetDictionary((EDictionaryType)dataDrivenSetup.DictionaryTypeID, 1, true);
                    element.DataSource = data;
                    element.ValueMember = "DictionaryID";
                    element.DisplayMember = "Description";
                    element.DropDownStyle = RadDropDownStyle.DropDownList;
                    e.Editor = dropDownListEditor;

                    break;
            }

        }

3 Answers, 1 is accepted

Sort by
0
Dess | Tech Support Engineer, Principal
Telerik team
answered on 25 Aug 2023, 12:02 PM

Hello, Carl,

Please have in mind that RadVirtualGrid manages the cell values in a different way compared to RadGridView. It doesn't store all cell values locally but loads the data on demand while scrolling, requesting what value to be displayed. This article gives more details on the topic:

https://docs.telerik.com/devtools/winforms/controls/virtualgrid/working-with-data/virtualgrid-populating-with-data 

Hence, in the EditorRequired event, it is necessary to use the column/row index, not accessing a data cell and checking what value type is stored in the cell. This should be performed by accessing the value from the external source from which you are extracting the data for filling the cells in the CellValueNeeded event. Then, in the CellEditorInitialized event you can fine-tune the editor and apply some settings:

- how to specify the type of the editor:

https://docs.telerik.com/devtools/winforms/controls/virtualgrid/editing/changing-default-editor  

- how to apply settings to the initialized editor. This is the appropriate place to set the commented properties for VirtualGridDateTimeEditor:

https://docs.telerik.com/devtools/winforms/controls/virtualgrid/editing/changing-editors-properties 

If following this suggestions still doesn't achieve the scenario you need to cover, it would be greatly appreciated if you can provide a complete code snippet that replicates the problem you are facing. Thus, we would be able to make an adequate analysis of the precise case and think about a suitable solution.

Regarding the question about checkboxes, I believe that the following article would be quite useful on this topic:

https://docs.telerik.com/devtools/winforms/controls/virtualgrid/cells/creating-custom-cells   

Regards,
Dess | Tech Support Engineer, Principal
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.

0
Carl
Top achievements
Rank 1
Iron
Iron
Iron
answered on 25 Aug 2023, 06:17 PM

Dess

For starters, I'm not using RadVirtualGrid. I'm using RadGridView. I made some mods based on your suggestions and the updated code is below.

1. The CheckBox solution you gave me was for a column of checkboxes. I only want a checkbox editor for a single cell when needed. I ended up using a ComboBox with Yes/No as options but if you can tell me how to show the check box that would be ideal.

2. Date works better now but it still shows the time portion. How can I display only the date?

3. For Numeric entry, I'd like to allow the user to enter numbers with a decimal, say 6 digits before and 2 digits after the decimal. What do I need to do here?

Note that the Value column where the user selects the value is bound to the following property:

public object? Value { get; set; }

Thanks

Carl

       void gvDataDriven_EditorRequired(object sender, EditorRequiredEventArgs e)
       {
           try
           {
               int dataDrivenSetupID = int.Parse(gvDataDriven.CurrentRow.Cells["DataDrivenSetupID"].Value.ToString());

               DataDrivenSetup dataDrivenSetup = _dataDrivenSetup.Where(n => n.DataDrivenSetupID == dataDrivenSetupID).FirstOrDefault();

               switch ((ControlType)dataDrivenSetup.ControlID)
               {
                   case ControlType.TextBox:

                       VirtualGridTextBoxEditor virtualGridTextBoxEditor = new VirtualGridTextBoxEditor();
                       virtualGridTextBoxEditor.MaxLength = dataDrivenSetup.MaxLength.Value;
                       e.Editor = virtualGridTextBoxEditor;
                       break;

                   case ControlType.NumericEntry:
                       VirtualGridMaskedEditBoxEditor virtualGridMaskedEditBoxEditor = new VirtualGridMaskedEditBoxEditor();
                       virtualGridMaskedEditBoxEditor.MaskTextBox.MaskType = MaskType.Numeric;
                       virtualGridMaskedEditBoxEditor.MaskTextBox.Mask = "D";
                       virtualGridMaskedEditBoxEditor.MaskTextBox.TextAlign = HorizontalAlignment.Right;
                       virtualGridMaskedEditBoxEditor.MaskTextBox.TextMaskFormat = MaskFormat.ExcludePromptAndLiterals;
                       e.Editor = virtualGridMaskedEditBoxEditor;
                       break;

                   case ControlType.DateEntry:
                       VirtualGridDateTimeEditor virtualGridDateTimeEditor = new VirtualGridDateTimeEditor();

                       var editorElement = virtualGridDateTimeEditor.EditorElement as RadDateTimeEditorElement;
                       editorElement.Format = DateTimePickerFormat.Custom;
                       editorElement.CustomFormat = "MM/dd/yyyy";
                       //editorElement.TextBoxElement.MaskType = MaskType.Standard;
                       e.Editor = virtualGridDateTimeEditor;
                       break;

                   case ControlType.CheckBox:
                       VirtualGridDropDownListEditor dropDownListEditorCheckBox = new VirtualGridDropDownListEditor();
                       RadDropDownListEditorElement elementCheckBox = dropDownListEditorCheckBox.EditorElement as RadDropDownListEditorElement;
                       elementCheckBox.Items.Add("Yes");
                       elementCheckBox.Items.Add("No");
                       elementCheckBox.Items.Add(string.Empty);
                       elementCheckBox.DropDownStyle = RadDropDownStyle.DropDownList;
                       e.Editor = dropDownListEditorCheckBox;
                       break;

                   case ControlType.ComboBox:
                       VirtualGridDropDownListEditor dropDownListEditor = new VirtualGridDropDownListEditor();
                       RadDropDownListEditorElement element = dropDownListEditor.EditorElement as RadDropDownListEditorElement;
                       List<Dictionary> data = CommonServices.GetDictionary((EDictionaryType)dataDrivenSetup.DictionaryTypeID, 1, true);
                       element.DataSource = data;
                       element.ValueMember = "Description";
                       element.DisplayMember = "Description";
                       element.DropDownStyle = RadDropDownStyle.DropDownList;
                       e.Editor = dropDownListEditor;
                       break;
               }
           }
           catch (Exception ex)
           {

           }

       }
0
Dess | Tech Support Engineer, Principal
Telerik team
answered on 30 Aug 2023, 11:31 AM

Hello, Carl,

Thank you for clarifying that you are using RadGridView. I was confused initially because the provided code snippet was relevant for RadVirtualGrid, not RadGridView.

I will provide the relevant information about RadGridView since my previous reply was focused on RadVirtualGrid. All default editors for the different column types in RadGridView are listed in the following article:
https://docs.telerik.com/devtools/winforms/controls/gridview/editors/default-editors

1. GridViewCheckBoxColumn displays and allows editing of boolean data. The values are shown as check boxes and allow the user to set or clear the check boxes to toggle the underlying boolean data values. The EditMode property controls when the value of the editor will be submitted to the cell. By default, the value will be submitted only when the current cell changes or the grid looses focus. Setting the property to OnValueChange will submit the value immediately after the editor value changes: https://docs.telerik.com/devtools/winforms/controls/gridview/columns/column-types/gridviewcheckboxcolumn

Another approach is to use a GridViewComboBoxColumn which displays a set of predefined text values in a drop down list: https://docs.telerik.com/devtools/winforms/controls/gridview/columns/column-types/gridviewcomboboxcolumn

It is possible to convert the cell value to a type that is compatible with the specific column. A sample approach is demonstrated here which shows how to convert char values Y and N to ToggleState values ToggleState.On and ToggleState.Off. :
https://docs.telerik.com/devtools/winforms/controls/gridview/columns/converting-data-types

2. GridViewDateTimeColumn provides date entry and formatting for DateTime data types. It is possible to specify the format for the cells and for the editor accordingly: https://docs.telerik.com/devtools/winforms/controls/gridview/columns/column-types/gridviewdatetimecolumn

3. GridViewDecimalColumn is appropriate for numeric input as it allows decimal data to be displayed and edited. Please refer to the below code snippet.

An alternative option is GridViewMaskBoxColumn allows restricted editing of text data. According to the applied mask you can restrict the format of the entered value: https://docs.telerik.com/devtools/winforms/controls/gridview/columns/column-types/gridviewmaskboxcolumn 
If you are not sure what mask is appropriate for you case, MSDN offers a suitable article on this topic: 
https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings?redirectedfrom=MSDN
Alternatively, you can use a Standard mask: https://docs.telerik.com/devtools/winforms/controls/editors/maskededitbox/standard-masks 

I have prepared a sample code snippet which shows how to fine-tune the columns with the appropriate settings. It is possible to adjust the activated editor once it is initialized by handling the CellEditorInitialized event and parsing to the respective editor according to the current column.

 

            GridViewCheckBoxColumn checkBoxColumn = new GridViewCheckBoxColumn("CheckBoxColumn");
            checkBoxColumn.DataType = typeof(int); 
            radGridView1.MasterTemplate.Columns.Add(checkBoxColumn);

            GridViewComboBoxColumn comboColumn = new GridViewComboBoxColumn("ComboColumn");
            comboColumn.DataSource = new List<string>() {"No", "Yes" }; 
            this.radGridView1.Columns.Add(comboColumn);

            GridViewDateTimeColumn dateTimeColumn = new GridViewDateTimeColumn("DateTimeColumn");
            dateTimeColumn.FilteringMode = GridViewTimeFilteringMode.Date;
            dateTimeColumn.FormatString = "{0:dd/MM/yyyy}";
            dateTimeColumn.Format = DateTimePickerFormat.Custom;
            dateTimeColumn.CustomFormat = "dd/MM/yyyy";
            radGridView1.MasterTemplate.Columns.Add(dateTimeColumn);         

            GridViewDecimalColumn decimalColumn = new GridViewDecimalColumn();
            decimalColumn.DecimalPlaces = 2;
            decimalColumn.Maximum=999999.99m;
            this.radGridView1.Columns.Add(decimalColumn);

            radGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
            this.radGridView1.Rows.Add(1, "Yes", DateTime.Now, 123.456m);

I believe that you will find the provided tips useful for achieving progress in the scenario you need to cover. Let me know is you need any further assistance.

Regards,
Dess | Tech Support Engineer, Principal
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 30 Aug 2023, 08:56 PM

Dess

I don't think I'm being clear. I don't have the option of one column per data type. Below shows what the requirement calls for:

I have a single column that will handle all data types because the _dataDrivenSetup variable contains an object that tells me what I'm working with. if I land on the Wedding Anniversary row it tells me that's a date and I should display a date control. if I land on the In rehab row it tells me I need a check box, and so on. How can I accomplish this in a single column?

Thanks

Carl

Dess | Tech Support Engineer, Principal
Telerik team
commented on 31 Aug 2023, 04:56 AM

Hi, Carl,

According to the provided screenshot, I would recommend you to consider using RadPropertyGrid which offers exactly the same design with the following code: 

            PropertyStoreItem item1 = new PropertyStoreItem(typeof(string), "Nick Name", "The Weasel");
            PropertyStoreItem item2 = new PropertyStoreItem(typeof(float), "Shoe Size", 8f);
            PropertyStoreItem item3 = new PropertyStoreItem(typeof(DateTime), "Wedding Anniversary", new DateTime(2002,7,8));
            PropertyStoreItem item4 = new PropertyStoreItem(typeof(MyEnum), "In rehab", MyEnum.Yes);
            PropertyStoreItem item5 = new PropertyStoreItem(typeof(MyEnum), "In rehab", MyEnum.Yes);
            RadPropertyStore store = new RadPropertyStore();
            store.Add(item1);
            store.Add(item2);
            store.Add(item3);
            store.Add(item4);
            this.radPropertyGrid1.SelectedObject = store;

Carl
Top achievements
Rank 1
Iron
Iron
Iron
commented on 31 Aug 2023, 08:05 PM

Dess

Thanks for this. RadPropertyGrid is exactly what I needed. I even have the checkbox now! There is just one little glitch left. In the code below, note how I'm editing the combo box info. The values are not in an enum. Rather, the values are in a database and are loaded into a List collection of objects. I can populate the RadDropDownList with it but it I specify the columns to display like this the value appears in the editor and not the text when I make a selection.

                element.ValueMember = "DictionaryID";

                element.DisplayMember = "Description";

I could set them both to Description and convert from text to numeric values when I send the data to and from the RadPropertyGrid but that would be a kludge I'd like to avoid. Any way I can do it?

I choose and item from here:

and it displays this:

Thanks

Carl

        private void LoadEditor()
        {
            RadPropertyStore store = new RadPropertyStore();
            PropertyStoreItem propertyStoreItem = null;

            foreach (var item in _dataDrivenSetup)
            {
                switch ((ControlType)item.ControlID)
                {
                    case ControlType.TextBox:
                    case ControlType.ComboBox:
                        propertyStoreItem = new PropertyStoreItem(typeof(string), item.Label, item.Value);
                        break;

                    case ControlType.NumericEntry:
                        propertyStoreItem = new PropertyStoreItem(typeof(decimal), item.Label, item.Value);
                        break;

                    case ControlType.DateEntry:
                        propertyStoreItem = new PropertyStoreItem(typeof(DateTime), item.Label, item.Value);
                        break;

                    case ControlType.CheckBox:
                        propertyStoreItem = new PropertyStoreItem(typeof(bool), item.Label, item.Value.ToString() == "1" ? true : false);
                        break;

                }

                store.Add(propertyStoreItem);
            }

            propDataDriven.SelectedObject = store;
        }

 

        private void propDataDriven_EditorRequired(object sender, PropertyGridEditorRequiredEventArgs e)
        {
            DataDrivenSetup dataDrivenSetup = _dataDrivenSetup.Where(n => n.Label == e.Item.Label).FirstOrDefault();

            if ((ControlType)dataDrivenSetup.ControlID == ControlType.ComboBox)
            {
                VirtualGridDropDownListEditor dropDownListEditor = new VirtualGridDropDownListEditor();
                RadDropDownListEditorElement element = dropDownListEditor.EditorElement as RadDropDownListEditorElement;
                List<Dictionary> data = CommonServices.GetDictionary((EDictionaryType)dataDrivenSetup.DictionaryTypeID, 1, true);
                element.DataSource = data;
                element.ValueMember = "Description";
                element.DisplayMember = "Description";
                element.DropDownStyle = RadDropDownStyle.DropDownList;
                e.Editor = dropDownListEditor;
            }
        }
Dess | Tech Support Engineer, Principal
Telerik team
commented on 04 Sep 2023, 03:33 PM

Hi, Carl,

The ValueMember property of RadDropDownListEditorElement  is expected to be specified to a compatible type with the value which is stored in the respective cell of the RadPropertyGrid.SelectedObject, e.g. "DictionaryID" in this case. However, if you want to control what text to be displayed in the item while it is not in edit mode, you can handle the ItemFormatting event and set the desired text according to the respective ID number. A sample code snippet is demonstrated below: 

        private void RadPropertyGrid1_ItemFormatting(object sender, PropertyGridItemFormattingEventArgs e)
        {
            if (e.Item.Label == "Account Type")
            {
                PropertyGridItemElement el = e.VisualElement as PropertyGridItemElement;
                if (el != null)
                {
                    el.ValueElement.Text = "this is the text you need to display";
                }
            }
        }

However, using a TypeConverter for this property and converting the numeric value to a corresponding string value is also a doable solution.

Carl
Top achievements
Rank 1
Iron
Iron
Iron
commented on 05 Sep 2023, 03:51 PM

Dess

This is exactly what I needed. Thanks. Let's marked this as answered and closed.

Carl

Tags
GridView
Asked by
Carl
Top achievements
Rank 1
Iron
Iron
Iron
Answers by
Dess | Tech Support Engineer, Principal
Telerik team
Carl
Top achievements
Rank 1
Iron
Iron
Iron
Share this question
or