FritzAndFriends / BlazorWebFormsComponents

A collection of Blazor components that emulate the ASP.NET Web Forms controls of the same name
MIT License
426 stars 72 forks source link

Data Binding Refactoring #239

Closed hishamco closed 4 years ago

hishamco commented 4 years ago

I just refactor the current APIs plus introduce some new one to make it almost similar to what we have in WebForms, I think after this PR I can start mark some of the components as DataBoundComponent to get the OnDataBound and for others OnDataBinding will be available

/cc @Eilon @csharpfritz

hishamco commented 4 years ago

FYI @csharpfritz the DataBinding features can't be all on the BaseDataBindingComponent anymore as you commented here I knew your principal is write but that's how WebForms implement the DataBinding APIs ;) I'm still wondering why?!! @Eilon any idea from 2001 days?

Eilon commented 4 years ago

@hishamco I'm not sure exactly what is being asked, but my general opinion is that the components type hierarchy here should closely (or identically) match the type hierarchy in Web Forms. I think that will make managing and extending the components here much easier. Otherwise we might end up with bizarre duplicated code or spaghetti logic.

While there certainly could be exceptions where we don't match the hierarchy, I would expect those to be well justified. One justification could simply be that Blazor can't represent certain things the way Web Forms did, so we were forced to do something different.

hishamco commented 4 years ago

I think what what I did here will simply the process otherwise we will ended up with almost the controls if not all inherits from BaseDataBindingComponent to avoid the that and make everything clear I separate the APIs, then the data binding feature will be easier IMHO

Eilon commented 4 years ago

In Web Forms we have:

  1. Control (the root of all controls) has the DataBind() method, which ensures that all the code in <%# Foo %> expressions is run. It's also a virtual methods, so individual controls can do any additional data-binding that makes sense for them.
  2. Then there is BaseDataBoundControl, which is the root type for commonly-used data-bound controls such as GridView, DropDownList, FormView, and many others. This adds a DataSource property, which can be assigned to some kind of list type (such as an IEnumerable, DataSet, etc.), and when DataBind() is called, this property is evaluated and then "binding" happens (e.g. the grid generates its rows, etc.).

So, in Web Forms, every control on every page supports databinding. The fancier controls such as GridView add some additional behavior when they databind to generate more controls based on lists of data.

hishamco commented 4 years ago

Also there is ItemDataBound that's special for DataList and ListView, but still not convinced why each control is data bindable?

Eilon commented 4 years ago

In Web Forms every control is bindable so that the framework can run the code in the <%# SomeValue %> expressions when it is inside a data-bound control.

In Blazor this is somewhat less of an issue because in Blazor you can just put any code expression anywhere and it will run at the right time. In Web Forms it was done via data-binding.

In Web Forms when you write code like this:

<asp:GridView ...>
    <Columns>
        <asp:TemplateField ...>
            <ItemTemplate>
                <asp:Label id="DataBoundLabel" Text="<%# DataItem.FirstName %>>" ... />
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

ASP.NET will generate code sort of like this:

DataBoundLabel.DataBinding += (s, e) =>
{
    DataBoundLabel.Text = DataItem.FirstName;
};

So when you call DataBind() on the GridView, it will do its databinding stuff (read the datasource, generate each row, etc.), and then the GridView calls DataBind() on each control inside each of its templates. This causes the Label named DataBoundLabel to run its DataBinding event handler, which will set the text to the current data item's FirstName property.

For this reason, every control has to be data-bindable so that it can have its properties set when it is inside another data-bound control.

Again, in Blazor, this is somewhat less important, so I'm not 100% certain what the exact design should be.

hishamco commented 4 years ago

Perhaps using them inside rich controls such a GridView and others is enough to make them bindable

Thanks Eilon

Eilon commented 4 years ago

Well, I think that the change proposed in this PR does bring things more in-line with what Web Forms does, so I think it helps move things forward. Maybe we'll later find some other change we'll want to make, but I think this gets us closer to what will work.

csharpfritz commented 4 years ago

Thank you for the update.... and we will want to review the Async call in the DataBinding method of the BaseWebFormsComponent

hishamco commented 4 years ago

Also I will continue to support the DataBinding() for the available components