ASP.net: Best practice to bind a form to an LLBLGen object source

Posts   
 
    
KIT
User
Posts: 59
Joined: 04-Apr-2007
# Posted on: 05-Apr-2007 09:25:27   

Hello!

I am having a complex form consisting of one parent .aspx file and several user controls (.ascx) placed on it. On all of the user controls there are textboxes, radio buttons and so on. All user controls should get the data from the same object source (same object instance). On the parent .aspx file there is a button "Save". When I click on it, all entered data should be gathered from the user controls and the object should be saved.

I think that is a quite common scenario and others should have done that already.

Now my question: What is the easiest way to implement the binding between the object source and the form fields. With ASP.net I can easily bind it in one way:

<asp:TextBox ID="txtName" runat="server" Text='<%# mEmployee.Name %>' />

However, unbinding the data to write it back into the database is not possible. What I want to have is a 2-way databinding. Yesterday I spent the whole afternoon to find a solution. Firstly, I tried it with the LLBLGenDataSource2. That didn't really work because I can only define it on the parent .aspx page but then the containing user controls (.ascx) cannot access the datasource. Then I tried several other suggestions (not related with LLBLGen) for a two-way databinding but none of them worked (e.g. because of conversion problems with dates).

How did you solve that? Do you have an example application or example code?

Thank you in advance for your help!

Cheers, Brad

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 05-Apr-2007 11:44:13   

Did you check the "Databinding with ASP.NET 2.0" section in the LLBLGen Pro manual?

Firstly, I tried it with the LLBLGenDataSource2. That didn't really work because I can only define it on the parent .aspx page but then the containing user controls (.ascx) cannot access the datasource.

As far as I know user controls can access any object in their containing page.

Would you please explain what are you displaying in the page and what are you displaying in the User controls? Are they master-detail data? Because you can have a dataSource in each and every user control, and a save button in the main page can go and call save methods in each user control, to save the data back in the database.

Then I tried several other suggestions (not related with LLBLGen) for a two-way databinding but none of them worked (e.g. because of conversion problems with dates).

I don't know what yo are talking about, here.

KIT
User
Posts: 59
Joined: 04-Apr-2007
# Posted on: 05-Apr-2007 15:45:28   

Did you check the "Databinding with ASP.NET 2.0" section in the LLBLGen Pro manual?

Yes simple_smile 2-way databinding with grids is working perfectly. But the particular case I have is not described in the manual.

As far as I know user controls can access any object in their containing page.

Ouups.. confused you're right. Sorry about that!

I will try to explain a bit more detailed what I wanna do. I have a dialog with several tabs. A tab is a user control. All fields on all tabs should get and write its data from the same object (it's an employee object with a lot of fields). So you suggested to put a datasource on every user control and the save button on the parent aspx page. But how can every datasource point to the same object? I also tried to bind the formView control to the datasource of the parent aspx control. But that doesn't work.. :-( The datasource has to be defined in the .ascx file. I can't define it in the code behind (.cs.ascx).

Sorry my question is maybe a bit stupid. I'm pretty new to LLBLGen. However, for the list it worked just great and it's a pleasure to work with that tool!

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 05-Apr-2007 16:02:32   

So you suggested to put a datasource on every user control and the save button on the parent aspx page. But how can every datasource point to the same object?

I thought they were different objects (related entities)

I also tried to bind the formView control to the datasource of the parent aspx control. But that doesn't work.. :-( The datasource has to be defined in the .ascx file. I can't define it in the code behind (.cs.ascx).

For each user control you can set its grid datasource at code behind, read from the container page. Just don't declaratively set it.

KIT
User
Posts: 59
Joined: 04-Apr-2007
# Posted on: 05-Apr-2007 17:42:18   

I thought they were different objects (related entities)

Nono, very simple. Just one object.. smile

I tried the solution you suggested. I think I'm nearly at the target but I'm still facing two problems:

  1. I put a datasource (livePersistence=false) and a save button on the parent aspx page. When clicking the save button the "[i]PerformWork[/i]" method is not executed. I also tried to access the DataSource.UnitOfWork object but it's null. So how can I commit the changes? "[i]PerformSelect[/i]" is executed properly when loading the page.

  2. I put some bound controls on the parent aspx page and some on the sub user controls (ascx). However, the databinding only works on the parent aspx page. Nothing is displayed on the user controls. Below some code lines:

Parent aspx:

<asp:FormView ID="FormView1" runat="server" DataSourceID="employeeDataSource"  DefaultMode="Edit" >
      <EditItemTemplate>
          <asp:TextBox ID="txtTest" runat="server" Text='<%#Eval("Name")%>' />
      </EditItemTemplate>
</asp:FormView>

<asp:Button ID="btnSave" runat="server" Text="Speichern" OnClick="btnSave_Click" />

<cc1:LLBLGenProDataSource2 ID="employeeDataSource" runat="server" AdapterTypeName="..." DataContainerType="EntityCollection" EntityFactoryTypeName="..." LivePersistence="false" OnPerformWork="eds_PerformWork" OnPerformSelect="eds_PerformSelect" />

--> Databinding here works good. Value is written to txtTest. However, as explained above I'm not able to commit the changes because eds_PerformWork is never executed.

Parent aspx code-behind:

public LLBLGenProDataSource2 DataSource {
        get { return employeeDataSource; } // property to provide DS for sub ascx files..
}


protected void eds_PerformSelect(object sender, PerformSelectEventArgs2 e) {

            EmployeeEntity employee = new EmployeeEntity(mId);
            mAdapter.FetchEntity(employee);
            employeeDataSource.EntityCollection.Add(employee);
}


protected void eds_PerformWork(object sender, PerformWorkEventArgs2 e) {
            e.Uow.Commit(mAdapter, true); // this is never executed!!!!
}

Now the user control:

ascx (HTML):

<asp:FormView ID="FormView1" runat="server" DataSourceID="employeeDataSource" >
      <ItemTemplate>
          <asp:TextBox ID="txtTest2" runat="server" Text='<%#Eval("Name")%>' />
      </ItemTemplate>
</asp:FormView>

<cc1:LLBLGenProDataSource2 ID="employeeDataSource" runat="server" AdapterTypeName="..." DataContainerType="EntityCollection" EntityFactoryTypeName="..." LivePersistence="false">
</cc1:LLBLGenProDataSource2>

--> The databinding here doesn't work.. nothing is written to txtTest2. Not even the HTML of the textbox is written to the UI..

ascx (code-behind):

protected void Page_Load(object sender, EventArgs e) {
      employeeDataSource = ((IDataSource) Page).DataSource; // get datasource from parent aspx and set it to internal datasource
}

Now I'm really, really curious what the error is! stuck_out_tongue_winking_eye

fpw2377
User
Posts: 35
Joined: 23-Feb-2007
# Posted on: 05-Apr-2007 21:05:28   

You might want to look at this

http://msdn.microsoft.com/msdnmag/issues/06/12/ExtendASPNET/default.aspx?loc=en

I have used it for simple databinding and it works great for me. I like the fact that I can do the binding in design mode. The article was written by Rick Strahl, here is his site.

http://www.west-wind.com/

Lots of great info and other free controls. I like the wwHoverpanel, you might want to check that one out too.

KIT
User
Posts: 59
Joined: 04-Apr-2007
# Posted on: 05-Apr-2007 22:24:17   

Thanks for the hint. I've tried that tool already before I wrote to the LLBLGen forum..

wwDataBinder didn't work in my application due to conversion problems in date fields.

I think it's an interesting tool for people not using object datasources. But somehow it's a workaround and it should actually also work with the LLBLGen datasource.. Anyway, thanks again..

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 06-Apr-2007 17:37:53   

--> Databinding here works good. Value is written to txtTest. However, as explained above I'm not able to commit the changes because eds_PerformWork is never executed.

That's really strange, which LLBLGen Pro runtime library version are you using?

KIT
User
Posts: 59
Joined: 04-Apr-2007
# Posted on: 10-Apr-2007 11:37:46   

That's really strange, which LLBLGen Pro runtime library version are you using?

The version of SD.LLBLGen.Pro.ORMSupportClasses.NET20.dll is 2.0.7.402. So it is a very recent one. However, it is still the same situation. "PerformWork" is not executed. I also checked if there are dirty entities in the datasource but there aren't.

KIT
User
Posts: 59
Joined: 04-Apr-2007
# Posted on: 10-Apr-2007 18:04:48   

Walaa are you still active in this thread?

In the meantime I figured out how one-way databinding works with nested user controls. However, I'm still having the problem that "PerformWork" is not executed. Can you confirm that this is a bug in an older version?

Btw, I found some bugs in the code I posted above: 1. <%#Eval("Name")%> should be <%#Bind("Name")%> 2. I found out that "PerformSelect" is firstly executed on the user controls and later on the parent aspx page. So I have to initialize the ascx-datasource a bit differently. That is working now.

--> Fixing these two problems did not change the situation. "PerformWork" does still not work. confused

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 11-Apr-2007 11:10:11   

The probelm is the following code:

<asp:FormView ID="FormView1" runat="server" DataSourceID="employeeDataSource" DefaultMode="Edit" >
     <EditItemTemplate>
         <asp:TextBox ID="txtTest" runat="server" Text='<%#Eval("Name")%>' />
     </EditItemTemplate>
</asp:FormView>

<asp:Button ID="btnSave" runat="server" Text="Speichern" OnClick="btnSave_Click" />

Move the button inside the EditTemplate of the FormView and set the CommandName to "Update", as follows:

<asp:FormView ID="FormView1" runat="server" DataSourceID="employeeDataSource" DefaultMode="Edit" >
     <EditItemTemplate>
         <asp:TextBox ID="txtTest" runat="server" Text='<%#Eval("Name")%>' />
         <asp:Button ID="btnSave" runat="server" Text="Speichern" CommandName="Update" />
     </EditItemTemplate>
</asp:FormView>

KIT
User
Posts: 59
Joined: 04-Apr-2007
# Posted on: 11-Apr-2007 11:19:03   

Oh god.. you are right. flushed flushed flushed flushed flushed

Sorry that wasn't an LLBLGen issue but rather an ASP.net problem.

Anyway, thank you 100000 times for your help!

simple_smile simple_smile simple_smile