still no design time dataset sharing among forms??

  • Thread starter Thread starter calgon
  • Start date Start date
C

calgon

I had heard about the BindingSource in .Net 2.0 and hoped it would solve
the problem of sharing dataset instances among forms. But now that I
study it more closely I think I was mistaken. It looks like it is just a
proxy for any kind of datasource and it has some of the old
currencymanager functionality..?

Anyway, is it still not possible to have a single dataset instance,
created at design time, and shared/bound by multiple forms? Do you still
have to do it in code? It was a great weakness in 1.1, which was
obviously designed only with web pages in mind. I hope it is solved in 2.0.
 
Surely other developers of winforms apps faced this problem. Do you just
abandon the possibility of using design time binding and do all binding
in code? I have done that for one project. We did create dataset
instances in our forms simply for designtime uses so we could format
grid columns, etc..

Has anyone tried to go ahead and give each form its own dataset
instance, then use Merge()/GetChanges() at runtime anytime there is a
focus change so you can keep the 'master' dataset up to date and sync
changes among forms?
 
Surely other developers of winforms apps faced this problem. Do you just
abandon the possibility of using design time binding and do all binding
in code? I have done that for one project. We did create dataset
instances in our forms simply for designtime uses so we could format
grid columns, etc..

Has anyone tried to go ahead and give each form its own dataset
instance, then use Merge()/GetChanges() at runtime anytime there is a
focus change so you can keep the 'master' dataset up to date and sync
changes among forms?

Please don't top-post.

If I understand your question you want to do something similar to
this: when your application starts, display a main form in which you
load, bind and display a data set. Then when a user presses a button,
display a second form and also bind its controls to the same dataset
as used in the main form.

This is no problem, and you can do most of it with the design time
tools. Here is one way of doing it. It's a bit long-winded, but it
shows what is happening. You can shortcut this by dragging and
dropping from the Data Sources window if you want. That creates
controls, dataset variables and binding sources automatically.


1. Design your dataset. I usually do this in its own assembly, to form
a Data-access layer.

2. On Form1, drag the dataset from the toolbox to the form. It will
appear at the bottom on the component tray. This will create a dataset
variable in your form. You can name it whatever you want.

3. I usually do all binding via BindingSources, so the next step is to
drag a BindingSource onto Form1 and rename it to something sensible.
In the properties window, edit its DataSource property. Under "Other
Data Sources -> Form1 List instances" you will see the data set. Pick
it. Then set the DataMember to whatever table you want. Configure
Filter and Sort properties as appropriate. Repeat for as many binding
sources as you want.

4. Add controls to the form and configure as appropriate. Again, this
can all be done in the properties window. For example, drag a text box
to the form. Under Data (Data Bindings), pick "Advanced". You can set
one or more bindings in here. In the binding combo you will want to
pick something from the BindingSource that you configured eg
"bindingSource1 - Name".

5. Repeat the design on your second form, but with one slight
modification: change the data set's modifier from Private to Public.

6. Now imagine we have a button click handler on Form1. We just need
to get Form2 to use the dataset we are managing on Form1:

using (Form2 f = new Form2()) {
f.theDataSet = this.theDataSet;
f.ShowDialog();
}


Alternatively, you can keep the variable private and create a Public
property on the form which allows you to set it.

The only bit of code you need to write by hand is something in Form1
to load data into the DataSet.

Get your dataset variables and binding sources set and the rest
follows pretty easily. I like to do it this way because it keeps the
binding code hidden in the Designer.cs, and lets me focus on my code.

BTW, one thing you will find with this approach is that when you are
on Form2 changes you make will be immediately reflected in Form1
unless you suspend binding. You will see this when you have the same
piece of data displayed in both forms simultaneously.
 
I will non-quote-post if you like as a compromise. I am against bottom
posting, but its pointless to debate.

So at design time you actually are creating dataset instances on each
form right? Theres no way around that. But thanks to the BindingSource
class new in 2.0 your step 6 will work at runtime. I was a bit confused
but now I see since all the bindings you create at design time reference
a bindingsource, you can just change the bindingsource's dataset out
from under it with no problems. It would not work in 1.1 because you
would have to change each and every binding to refer to the new dataset.

Am I correct?

thanks
 
So at design time you actually are creating dataset instances on each
form right?

Yes, if by dataset instance you mean "a reference to a dataset
object". Think of it this way - there is one "dataset object" in your
application, taking up RAM, and you only need to fill it with data
once. But you can have multiple references to it, so you just setup
multiple references from every form that you need it on. You create a
reference variable by dragging and dropping the dataset from the
toolbox.

When you drag out your dataset to the form the variable instance is
generated in the Designer.cs and it is "null" unless you do something
with it. BUT - the WinForms designer is smart enough to use reflection
to query the *type* of the variable, and once it has done that it can
make all the design time binding functionality available to you.

At run time, you still need to give the second form some data to work
with - that's why you set the reference from the first form.

Theres no way around that.

Not if you want to use the design time binding. But remember it's only
a reference.
But thanks to the BindingSource
class new in 2.0 your step 6 will work at runtime. I was a bit confused
but now I see since all the bindings you create at design time reference
a bindingsource, you can just change the bindingsource's dataset out
from under it with no problems. It would not work in 1.1 because you
would have to change each and every binding to refer to the new dataset.

Am I correct?

thanks

Almost. The BindingSources are irrelevant to the technique I showed
you. You could omit the BindingSources and bind directly to the
DataSet if you want, and the technique I showed would still work. I
just like to use BindingSources, the filtering and sorting comes in
very handy.
 
Yes, if by dataset instance you mean "a reference to a dataset
object". Think of it this way - there is one "dataset object" in your
application, taking up RAM, and you only need to fill it with data
once. But you can have multiple references to it, so you just setup
multiple references from every form that you need it on. You create a
reference variable by dragging and dropping the dataset from the
toolbox.

Right, but are you sure thats what is happening? Im looking into the
generated InitializeComponent() code and seeing that each form is newing
a new instance of its own dataset. So yes each form has a member
variable which stores a reference to a dataset, but each is also
creating its own dataset instance. If you were to bind directly to it
and not through a BindingSource, simply reassigning the member variable
afterwards won't reassign all those bindings which occur in
InitializeComponent(). (Unless bindings bind to a ** pointer-pointer??!
sorry my c/c++ background) So im not seeing that there is a single
app/project wide dataset, though we can implement it at runtime, and do
designtime binding thanks to BindingSource as you showed me. So thats good.

At least this is what im seeing with C# Express, maybe full version is
generating different code?

Thanks, understanding issues like this is important to me. Im sure many
developers are implementing centralized datalayers and also wanting to
use design time data features. In 1.1 there was no real solution except
hacks like changing the InitializeComponent() code, which would then get
overwritten every time you opened your form in designer.
 
Back
Top