views:

421

answers:

1

Hi,

I am a little bit puzzled as to how I can optimize my program by utlizing DataBindings. My program uses several Linq2SQL bound Objects storing the Data. All ORM objects are stored in a hierarchy. In a second GUI project I am displaying this data in some Text and Combo Box fields.

The data structure hierarchy is as follows:

  • JobManager contains a Dictionary of Jobs
  • Each Job contains a Dictionary of Jobitems
  • Each Jobitem contains exactly one Article

Job, Jobitem and Article each are Linq2SQL objects, representing a ORM.

Now I have a GUI with 2 list views and a tab pane. The tab pane displays the properties of jobs, jobitems and articles and offers the possibility to modify jobs and jobitems. The GUI should behave like this:

  1. When a Job is selected in the first ListView, the related jobitems will be shown in the second ListView and detail information about the job are shown in the tab pane.
  2. When a Jobitem is selected in the second ListView, the jobitem details and article details are shown in the tab pane, but only the Jobitem info is editable.
  3. When changes are done, the user has to intentionally save them. Otherwise the changes should be discarded and not synced to the database.

How can I achieve this behaviour with DataBinding?

Especially, can I bind a complete collection to a single TextField once and shift through its position dictated by the selection in the ListViews? Or do I have to add and remove individual DataBindings on a per Job basis for every selection the user conducts?

+3  A: 

Do you really mean "Dictionary"? Winform binding is OK with lists (IList/IListSource), but not with dictionary. Additionally, ListView isn't quite as easy to bind to as some other controls.

Other than that, it should work purely using the mapping names - I'll try to do a simple example...


Edit with basic example from Northwind; note that the data-context should ideally not be long lived; you may also want to look at things like repository implementations rather than direct binding:

using System;
using System.Windows.Forms;
using SomeNamespaceWithMyDataContext;
static class Program
{
    [STAThread]
    static void Main() {
        MyDataContext ctx = new MyDataContext();
        BindingSource custs = new BindingSource() {
            DataSource = ctx.Customers};

        BindingSource orders = new BindingSource {
            DataMember = "Orders", DataSource = custs};

        Button btn;
        using (Form form = new Form
        {
            Controls = {
                new DataGridView() {
                    DataSource = orders, DataMember = "Order_Details",
                    Dock = DockStyle.Fill},
                new ComboBox() {
                    DataSource = orders, DisplayMember = "OrderID",
                    Dock = DockStyle.Top},
                new ComboBox() {
                    DataSource = custs, DisplayMember = "CompanyName",
                    Dock = DockStyle.Top},                
                (btn = new Button() {
                    Text = "Save", Dock = DockStyle.Bottom
                }), // **edit here re textbox etc**
                new TextBox {
                    DataBindings = {{"Text", orders, "ShipAddress"}},
                    Dock = DockStyle.Bottom
                },
                new Label {
                    DataBindings = {{"Text", custs, "ContactName"}},
                    Dock = DockStyle.Top
                },
                new Label {
                    DataBindings = {{"Text", orders, "RequiredDate"}},
                    Dock = DockStyle.Bottom
                }
            }
        })
        {
            btn.Click += delegate {
                form.Text = "Saving...";
                ctx.SubmitChanges();
                form.Text = "Saved";
            };
            Application.Run(form);
        }
    }
}

As an aside - note that the syntax:

DataBindings = {{"Text", orders, "ShipAddress"}}

Is equivalent to:

someTextBox.DataBindings.Add("Text", orders, "ShipAddress");

(I only add this as it is a common question)

Marc Gravell
First of all, thanks for the elaborate reply!I didn't know it's not working with Dictionaries, but alas Dictionaries are what I've got from the existing design. I could convert them to temporary lists, though, and as soon as the user hits "save" they could be transfered back into the dictionary to store the changes in the database. This would solve my third point as well.What about textfields? How would I bind a text file for "name" of a single job? Once with the complete job list as DataSource or every time with the specific job at hand?
Michael Barth
Adding some text fields...
Marc Gravell
And this way I can get single jobs to be displayed in the TextField by using e.g. this.BindingContext[custs,"ContactName"].Position?
Michael Barth
I don't fully understand the question; but the "currency manager" for "custs" will be pinned to whatever the selected custom is; if you want a specific customer, just use that customer instance directly in the binding source...
Marc Gravell