Declined
Last Updated: 03 Aug 2022 10:28 by ADMIN
Martin
Created on: 25 Jul 2022 11:52
Category: UI for WinForms
Type: Bug Report
0
RadGridView.OnCreateRowInfo not being called when user is adding a new row.

I have made an override for class GridViewDataRowInfo (called GridViewDataRowInfoPlus)

Every time a new row is created by RadGridView, I expect OnCreateRowInfo to be called, so I can return my own instance of GridViewDataRowInfoPlus.

This goes well until a user enters new data in a new row and when this row is added the grid, OnCreateRowInfo is not being called and an instance of GridViewDataRowInfo is added to the grid.

For me that is unexpected and undesirable. Maybe I am doing it wrong. In that case: What is the correct way to intercept the row-creation-process and return instances of my own type?

5 comments
ADMIN
Dess | Tech Support Engineer, Principal
Posted on: 03 Aug 2022 10:28

Hello, Martin,    

I really appreciate the provided feedback as it is helpful for making UI for WinForms a better product. However, please note that RadGridView is a complex control that provides a great diversity of features. Hence, its internal implementation is not always manageable according to all requests that our customers have. Even though we strive to provide as good public API as possible, there are numerous factors and core implementation that affect the API. Sometimes these factors are not obvious to the customers and we provide solid explanation how a certain functionality works. When it comes to creating a custom control deriving from RadGridView, it is better to contact the Telerik WinForms support and share what is the exact goal that you are trying to achieve than to create the custom implementation assuming that it works in a specific way. Thus, we can provide guidance how to accomplish a certain task. 

Now, I will go straight to previously listed topics:

1. I understand the convention you are referring to and I believe it is followed here:

The CreateRowInfo event is available for the RadGridView control and for its MasterTemplate:

	    _grid = new RadGridViewPlus();
            _grid.CreateRowInfo += _grid_CreateRowInfo;
            _grid.MasterTemplate.CreateRowInfo += MasterTemplate_CreateRowInfo;

If you handle the MasterTemplate.CreateRowInfo event and replace the newly added row via the new row UI, it is correctly replaced:

        private void MasterTemplate_CreateRowInfo(object sender, GridViewCreateRowInfoEventArgs e)
        {
			if (e.RowInfo is GridViewDataRowInfo)
			{
				e.RowInfo = new GridViewDataRowInfoPlus(e.ViewInfo);
			}
		}

The RadGridView.CreateRowInfo event is not used here.

        private void _grid_CreateRowInfo(object sender, GridViewCreateRowInfoEventArgs e)
        {
           
        }

2. I believe that 1. gives you the appropriate API that you can use in this scenario.

 

3. I agree that it is not a generic approach as it should be adopted to the specific DataSource collection that is assigned to the grid. The UserAddingRow event is commonly used for validating the data inside the new row before coming it to the grid. Thus, cancelling the UserAddingRow event will prevent the row to be added as a data row. More information on this topic is available here:
https://docs.telerik.com/devtools/winforms/controls/gridview/rows/new-row#user-events 

4. The internal workflow when using the new row UI handles the new row via the OnCreateRowInfo method of the MasterTemplate, not the OnCreateRowInfo method of the RadGridView itself. That is why there are events  at RadGridView level that are specifically introduced for handling the new row UI: UserAddingRow and UserAddedRow. They are documented in the online docs article referred above. These events were introduced a very long time ago and they are still serving the purposes that most of our customers have.

5. Thank you for filling the roadmap survey. It will definitely add value to the future planning of the product. As to the difficulties that you may experience during the development process, note that we are always here to help. The Telerik Technical Support is well familiar with the product and  how it is implemented. So if you have any difficulties or need some guidance, feel free to contact us and we will gladly assist you.

I hope that you will find the provided information useful.

Regards,
Dess | Tech Support Engineer, Principal
Progress Telerik

The Premier Dev Conference is back! 

Coming to you live from Progress360 in-person or on your own time, DevReach for all. Register Today.


Martin
Posted on: 29 Jul 2022 09:20

You have given me several suggestions. I will address them one by one.

1. You said: "I would like to note that the appropriate ways to replace the default GridViewDataRowInfo instances with your custom ones is to subscribe to the CreateRowInfo event that RadGridView offers". I disagree. First, in this case, it would not change anything, I tested it. If it DID change anything, it would be a new bug, since convention dictates the OnXXX should call the XXX-event, nothing more, nothing less. If the OnXXX contains more logic, convention is not followed. If event XXX is called from another location, convention is not follow. By overriding the OnXXX-method I was following convention. To quote Microsoft (see: https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/event): "The purpose of the method is to provide a way for a derived class to handle the event using an override. Overriding is a more flexible, faster, and more natural way to handle base class events in derived classes. By convention, the name of the method should start with "On" and be followed with the name of the event."

2. You said: "While the new row UI is used, the grid control suspends its notifications and the CreateRowInfo event wouldn't be fired until resuming the suspended notifications.". What are you trying to tell me here? This sounds like a technical reason why something is not working, not a functional reason. (In my company we sometimes say: technical reasons are most of the time technical excuses).Suspending notifications might be there for performance reasons, or other (technical) reasons. But it does not remove the fact that "OnCreatedRowInfo", which gives the user the feeling this is called while creating rows, is not called. Maybe I should create a new feature request: I need a method that is ALWAYS called when a new row is created (without any events attached to it, so it does not need suspending). Would that be a correct way to go? Yet another method with almost the same functionality?

3. Intercepting the UserAddingRow-event and add a DataRow to the databound DataTable is not a generic solution. It would only work for grid with a datatable. What about when I bind it to another datasource? I admit my example contained a DataTable, but it could have been any other datasource. I am overriding your controls to add new generic functionality which can be used in all our projects. Furthermore, adding a DataRow to the DataTable, will most likely fail to use all the other stuff the grid offers like validation. 

4. You said: "An alternative solution that I can suggest is to use the following approach". Yes! This one works. So thank you for that. But... wait a minute. Why is MasterGridViewTemplate.OnCreateRowInfo fired? Are events not suspended at that moment? Is this consistent?

5. Today I filled out your "2023 Roadmap Surveys". One of the biggest issues I have with Telerik is this kind of complexity en inconsistencies. All the (sub)elements, (sub)template with (sub)elements, seemingly duplicate methods A is suspended, but B is not. Which class should I override? Which method should I override? Advice that contradicts convention does not help either. I really appreciate your help in this cases and other cases, but... should it really be this hard?

ADMIN
Dess | Tech Support Engineer, Principal
Posted on: 28 Jul 2022 12:07
Hello, Martin,    

The provided sample project is greatly appreciated. I have reviewed the implementation of RadGridView that you have: 
	public class RadGridViewPlus: RadGridView
	{
		public RadGridViewPlus()
		{
			ThemeClassName = typeof(RadGridView).FullName;
		}

		protected override void OnCreateRowInfo(object sender, GridViewCreateRowInfoEventArgs e)
		{
			base.OnCreateRowInfo(sender, e);
			if (e.RowInfo is GridViewDataRowInfo)
				e.RowInfo = new GridViewDataRowInfoPlus(e.ViewInfo);
		}
	}

Indeed, the OnCreateRowInfo method that RadGridView offers is not called when you are manually adding a new row to the grid as different internal logic is performed. However, I would like to note that the appropriate ways to replace the default GridViewDataRowInfo instances with your custom ones is to subscribe to the CreateRowInfo event that RadGridView offers. While the new row UI is used, the grid control suspends its notifications and the CreateRowInfo event wouldn't be fired until resuming the suspended notifications. A specific event for handling adding the new row via the UI is the UserAddingRow event. Thus, you can cancel the default row and add programmatically a new record to the assigned DataSource:

        private void _grid_UserAddingRow(object sender, GridViewRowCancelEventArgs e)
        {
			e.Cancel = true; 
			DataTable dt = e.Rows[0].ViewTemplate.DataSource as DataTable;
			DataRow dr=dt.NewRow();
			foreach (GridViewCellInfo cell in e.Rows[0].Cells)
			{
				dr[cell.ColumnInfo.Name] = cell.Value;
			}
			dt.Rows.Add(dr);
		}

Thus, the desired custom row will be created:

An alternative solution that I can suggest is to use the following approach: 

public class RadGridViewPlus: RadGridView
{
	public RadGridViewPlus()
	{
		ThemeClassName = typeof(RadGridView).FullName;
	} 

    protected override RadGridViewElement CreateGridViewElement()
    {
        return new CustomRadGridViewElement();
    }
}

public class CustomRadGridViewElement: RadGridViewElement
{
    protected override MasterGridViewTemplate CreateTemplate()
    {
        return new CustomMasterGridViewTemplate();
    } 
}

public class CustomMasterGridViewTemplate : MasterGridViewTemplate
{
    protected override void OnCreateRowInfo(GridViewCreateRowInfoEventArgs e)
    {
        base.OnCreateRowInfo(e);
        if (e.RowInfo is GridViewDataRowInfo)
            e.RowInfo = new GridViewDataRowInfoPlus(e.ViewInfo);
    }
}

Feel free to use this approach which suits your requirements best.

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.

Martin
Posted on: 27 Jul 2022 11:38

I have written a little demo.

The bug is about RadGridViewPlus GridViewDataRowInfoPlus in combination with RadGridViewPlus.OnCreateRowInfo. And yes I really need / want to overwrite thoses classes, which is allowed, right?

The rest of the project (RadFrom) is simply for the demo. It loads a simple datatable with two record. While filling the RadGridViewPlus with those records, OnCreateRowInfo is being called which returns GridViewDataRowInfoPlus.

Now, try to add a record manually (i.e. with 3 and "Test"). When that record is added, OnCreateRowInfo is not called and GridViewDataRowInfo (without the Plus) is being added to the grid.

The big question is: Why was OnCreateRowInfo not being called?

 

Attached Files:
ADMIN
Dess | Tech Support Engineer, Principal
Posted on: 25 Jul 2022 11:56

Hello, Martin,

I am sorry to hear that you are experiencing any difficulties with the Telerik Ui for WinForms suite and the RadGridView control.

You should subscribe to the CreateRowInfo event at design time in order to ensure that the event will be fired when a data row have to be created. A sample approach for creating custom data rows is demonstarted here: https://docs.telerik.com/devtools/winforms/controls/gridview/rows/creating-custom-rows 

Could you please specify whether you are using a similar approach? It would be greatly appreciated if you can provide a sample runnable project demonstrating the undesired behavior that you are facing. Thus, we would be able to make an adequate analysis of the precise case and provide further assistance.

Thank you in advance for your cooperation. I am looking forward to your reply.

Regards,
Dess | Tech Support Engineer, Principal
Progress Telerik

The Premier Dev Conference is back! 

Coming to you live from Progress360 in-person or on your own time, DevReach for all. Register Today.