StrataFrame Forum

Difference between user control and form

http://forum.strataframe.net/Topic17845.aspx

By David Daragon - 7/14/2008

Hi,

I'm still making tests.

I put a list view in a Micro Four User Control which is contained in a Micro Four Form and the time of loading is 2800 ms.

When I put directly the same list in a Micro Four Form, the time is about 450 ms.

What are the reasons of this difference ?

Best regards

David

By Trent L. Taylor - 7/15/2008

To be honest, I am not sure.  This sounds as though it may be more specific to your code versus using a User Control and Form.  We actually use a lot of User Controls within our applications for reusability purposes.  You are welcome to post your sample here on the forum, but when it comes to timings like this, there is really no way for me to give you any type of straight answer without actually being able to see, test, and execute the code so a determination can be made.  But I can assure you that 2800ms is a very poor performance indeed and is not typical of this type of setup.
By David Daragon - 7/15/2008

Hi Trent,

I put my BO in my user control and I raise the ParentFormLoading event in userControl_Load event.

I saw that there is no PrimaryBusinessObject property in a user control.

Should I put a BO in the form which contains the user control ? I don't think so.

Could you help me by telling me the procedure to follow.

Thanks in advance

David

By David Daragon - 7/16/2008

Hi,

I retried this afternoon and I found the same result. I can't succeed to find where the problem is.

I need your help.

David

By David Daragon - 7/17/2008

Hi,

I succeed to have the same time of loading when I put a list directly in a form and when I put a list in user control contained in a form.

The problem seems to come from the parameters of the BOTranslation I did.

So, now, I have a time of loading equals to 520 ms in a user control. It's better Smile

But, I'm trying to do this by code but my list doesn't load Crying

I have this code in my form_load:

            ucClient _ucClient = new ucClient();

            _ucClient.Dock = DockStyle.Fill;

            _ucClient.Visible = true;

            _ucClient.OnFermerFenetre += new EventHandler(_ucClient_OnFermerFenetre);

            this.Controls.Add(_ucClient);

            BusinessObjectTranslationItem _BOTranslationItem1 = new BusinessObjectTranslationItem();

            _BOTranslationItem1.SourceBusinessObject = "Form1.clientBO1";

            _BOTranslationItem1.DestinationBusinessObject = "_ucClient.clientBO1";

            _ucClient.BOTranslations.AddRange(new BusinessObjectTranslationItem[] { _BOTranslationItem1 });

            _ucClient.BOTranslations.Add(_BOTranslationItem1);

            _ucClient.TranslationObject = this;

What's wrong ?

Thanks for your help.

David

By David Daragon - 7/17/2008

Just one more thing, there is an error in my code.

The line "_ucClient.BOTranslations.Add(_BOTranslationItem1);" isn't not in my code.

David

By Trent L. Taylor - 7/17/2008

David,

First, I think that you are making this harder than you need to in regards to the user control.  Just for a little background, we have a large number of user controls that are used within dialogs and forms which in turn use the BO translations between the two.  Here is how a user control is intended to work:

  1. Drop your BOs on a user control and bind to them just as though they were on a form
  2. Once the user control is written, drop that user control on a form or dialog
  3. Drop on the BOs of the same type that were dropped on the user control
  4. Then build the project
  5. Stay within the designer, and select the user control
  6. Go the BO Translations of the user control and click the "..." button
  7. This will then bring up a translations dialog.  Add a translation for each BO that needs to be translated from the dialog into the user control...they will have to be of the same BO type on each translation (one for one).
  8. Now populate the BOs on the form (or the user control can populate them if this is how you intend your app to work, but just for arguments sake, lets populate the Bos on the dialog here)
  9. Now when you run, you should be able to populate the BOs on the form and you will see them reflected within the user control
By David Daragon - 7/17/2008

Thanks for your help Trent,

I follow your method and it's work.

But if I want to do the same by code and not by the designer, I don't manage to laod my list.

Do I forget something in the code I posted before ?

David

By Trent L. Taylor - 7/17/2008

Gotcha....yes, you can do this in code, but you will have to do it in the OnLoad prior to the MyBase.OnLoad gets called so that the translations take place in the natural or expected order.  This is actually something that we do a bit ourselves.
By David Daragon - 7/17/2008

In which OnLoad ? In the form or in the user control ?
By Trent L. Taylor - 7/19/2008

Really either.  It depends on what you are trying to accomplish with the user control.  But if you add this before the MyBase.OnLoad method when overriding the OnLoad of the form, you will be fairly certain to create the translations before any translations take place.
By David Daragon - 7/20/2008

Hi Trent,

In fact, I want to use User Control to re use them in several screens. So I want to use code to create dynamicly my user controls and  I don't manage to create translations between my form and my user control.

When I put my user control in my form on the designer it works correctly.

Nevertheless, when I do the same by code by creating myself translations in the Form_Load(), it doesn't work. I put code before the InitializeComponent() and after but the result is the same.

What can I do ?

Thanks

David

By Trent L. Taylor - 7/21/2008

What can I do ?

Well, let's go at it from this perspective.  The BOs get translated within the Load of the form.  The SF users controls also have a property that exposes which object from which to translate.  I am not answering from a machine with VS on it (long story), but the user control has a property called TranslationObject (I think), but it will be iin the same category as the BOTranslations property of the UserControl.

You can set this to the form (or even set it in code) and it may resolve your problem.  If not, you can also implement the IParentFormLoading interface to control the initialization of the control.  But let's start with the first before we get into the second.

By David Daragon - 7/21/2008

Hello Trent,

Here is my code.

public partial class Form1 : MicroFour.StrataFrame.UI.Windows.Forms.StandardForm

{

private ClientBO _clientBO;

private BusinessObjectTranslationItem _BOTranslationItem1 = new BusinessObjectTranslationItem();

private ucClient _ucClient;

 

public Form1()

{

InitializeComponent();

_clientBO = new ClientBO();

_ucClient = new ucClient();

_clientBO.ParentContainer = this;

_clientBO.SynchronizingObject = this;

this.PrimaryBusinessObject = _clientBO;

this.Width = 1000;

this.Height = 750;

this.WindowState = FormWindowState.Normal;

_BOTranslationItem1.DestinationBusinessObject = "_ucClient.clientBO1";

_BOTranslationItem1.SourceBusinessObject = "Form1._clientBO";

_ucClient.BOTranslations.AddRange(new MicroFour.StrataFrame.UI.Windows.Forms.BusinessObjectTranslationItem[] {

_BOTranslationItem1});

_ucClient.Dock = System.Windows.Forms.DockStyle.Fill;

_ucClient.ParentContainer = this;

_ucClient.TranslationObject = this;

}

private void Form1_Load(object sender, EventArgs e)

{

_ucClient.Visible = true;

_ucClient.OnFermerFenetre += new EventHandler(_ucClient_OnFermerFenetre);

 this.Controls.Add(_ucClient);

}

void _ucClient_OnFermerFenetre(object sender, EventArgs e)

{

((MicroFour.StrataFrame.UI.Windows.Forms.UserControl)(sender)).ParentForm.Close();

}

}

I already set the TranslationObject property of my user control to my form. So, I will implement the IParentFormLoading interface to control the initialization of the control as you said.

David

By Trent L. Taylor - 7/21/2008

I really think that something is missing.  I don't think that the IParentFormLoading event will be your solution from looking at your code.  We are in the field training again this week, so our time is a bit limited.  However, instead of going back and forth, just create a simple sample and then we will take a look instead of going back and forth via the forum.
By David Daragon - 7/21/2008

Hi Trent,

I send you a sample project. I put the 2 examples. One with my user control created directly on the form by the designer which works. The other in which I create the user control and BOTranslation in the code.

David

By David Daragon - 7/29/2008

Hi

Did you have the time to test my sample ?

Regards,

David

By Trent L. Taylor - 7/30/2008

I will take a look at this soon, but we have just gotten back from being on the road and have a lot going on and we also have a lot of people out on vacation, so we are still trying to catch up.  Thank you for being patient.
By David Daragon - 7/30/2008

No worry Trent I just want to know to organize my work.

I will work with Strataframe for many years so I have time BigGrin

By David Daragon - 8/11/2008

no issue at my problem ?
By Dustin Taylor - 8/12/2008

Hi David!

Could you re-post that sample with the infragistic references and toolstrips removed? We don't have the version of infragistics you are using, so we can't build the project as is.

Thanks!

By David Daragon - 8/13/2008

Hi Dustin,

Here is a new sample without Infragistics references.
In my table, I have 4 columns CodeClient, Nom, CodePostal and Adresse as you can see in my BO.designer.cs.

I don't succeed to load my list when I create manually my uc in my form.
And I don't know why.

Hope this sample will work on your computer.

Regards,

David

By David Daragon - 8/13/2008

It would be better with the attachment BigGrin Wink
By Trent L. Taylor - 8/13/2008

OK, there are actually a lot of issues with your approach here and none are related to the BO translations.  Now keep in mind that the forum is not intended for training purposes, but I am going to briefly break down where your issues are:

  1. You need to ensure that your projects enforce invalid variable declarations, etc. at compile time.  You can turn some compiler errors off, and this is not the crux of the issue, but bottom line is that you want to see all errors during a compile...let nothing be ignored.
  2. You are not properly using the ListView.  First of all, on your user control, you have a ListView that has a PopulationDataSourceSettings set to call your ReturnClientList() (I am paraphrasing here on your method name).  This will never work.  A ListView creates an internal BO.  In your user control, you do not reference or load from the clientBO1 anywhere.  So obviously you are not going to be able to load from that BO.  In your PopulationDataSourceSettings you need to set the Method To Invoke to CopyDataFrom, the you will handle the ListPopulating event to provide the clientBO1 there so that the instance you are trying to translate will appear.  There are a lot of samples on the forum as well as in the install of SF showing how to poipulate a ListView this way...including many examples in the StrataFlix sample.  Please refer to these samples to learn how to populate a ListView this way.
  3. Once you work through these problems, you will need to override the OnLoad method instead of handling the event (though you can handle the event, overriding the OnLoad gives you the control to place your code before or after the base logic...just good .NET standards).  When you setup a BO translation, all of this will be done within the OnLoad of the form and the controls...so you will want to place your logic there.  Now once the BO is translated....YOU WILL HAVE to requery the ListView in order to get the updated contents of the translated BO into the ListView.

    lstClients.Requery()

That should be enough to get you going down the right path. Smile

By David Daragon - 9/3/2008

Hi

I succeed to load a listview in an user control with a designer. But I'm not sure you understand my problem.
I want to add an user control by code
UserControl _uc = new UserControl();

I wonder how to link a BO in the form and in the user control in the code and set the PopulationDataSourceSettings.

By Greg McGuffey - 9/3/2008

If I understand you correctly, you want to programatically add your user control (that contains a listview) to a form, then setup the listview to use data from a BO on the form. Assuming this is what you want to do, you have a few options:



- Expose the listview as a readonly property of the user control so you can setup it up in code. I.e. you'd use client code (the code in your form) something like:



UserControl _uc = new UserControl();

//Setup list population settings..

_uc.List.PopulationDataSourceSettings.MethodToExecute = "CopyDataFrom;BusinessLayer,BusinessCloneDataType";

// Add handler for list population (populateList would be the method on the form

// that handles this event)

_uc.List.ListPopulating += new ListPopulatingEventHandler(this.populateList);




- If you are always going to populate the list view from an external BO using CopyDataFrom, you'd be better off to just setup the listview in the user control that way, and add a BO property to your user control of type BusinessLayer. You'd then handle the ListPopulating event within the user control. The client code would then become:



UserControl _uc = new UserControl();

// Set BO

_uc.BusinessObject = this.MyLocalBO; //MyLocalBO being the one you want to load from




The code may not be entirely accurate, I just typed it in, but hopefully it gives you an idea of what you might want to do. BigGrin
By David Daragon - 9/4/2008

You're right Greg. I want to programatically add an user control in my form.

I set the properties by code but nothing happened. I may forgot something but why I don't know.

public Form1()
{

InitializeComponent();

_clientBO = new ClientBO();
_clientBO.ParentFormLoading +=
new MicroFour.StrataFrame.UI.IInitOnFormLoad.ParentFormLoadingEventHandler(_clientBO_ParentFormLoading);

_clientBO.ParentContainer = this;
_clientBO.SynchronizingObject =
this;

_ucClient = new ucClient();

this.PrimaryBusinessObject = _clientBO;
_BOTranslationItem1.DestinationBusinessObject = "_ucClient.clientBO1";
_BOTranslationItem1.SourceBusinessObject =
"Form1._clientBO";

_ucClient.BOTranslations.AddRange(new MicroFour.StrataFrame.UI.Windows.Forms.BusinessObjectTranslationItem[] {

_BOTranslationItem1});

_ucClient.Dock = System.Windows.Forms.DockStyle.Fill;

_ucClient.ParentContainer = this;
_ucClient.TranslationObject =
this;

this.Controls.Add(_ucClient);

}

void _clientBO_ParentFormLoading()
{
_clientBO.RetournerTousClients();
}

By Greg McGuffey - 9/4/2008

David,



I see a couple of things that don't make sense:



- Were are you calling Requery() on the listview in your user control?



- I'm thinking that _clientBO.RetournerTousClients(); is a fill method that fills the _clientBO with data. Are you thinking that this will somehow fill your listview? Even if the listview is configured to use the same type of BO as the local instance _clientBO, it won't use that instance. The listview creates its own instance.



If you'd like to use the data from _clientBO to fill the listview, then you need to configure the listview to use the CopyDataFrom method using the businesslayer overload. Then you must either pass in the appropriate parameters to the Requery() method OR handle the ListPopulating method and provide those parameters. In almost all cases it is better to handle the event. Hope this is starting to make sense.