?
Solved

Refresh form when already open and it's combo box

Posted on 2008-11-14
9
Medium Priority
?
2,329 Views
Last Modified: 2013-12-17
Hi

I have a MDI app with multiple forms with Telerik DockingManager witch is a container for all childforms.

I have a form to Edit Users where you select the user with a combo box.
This is how I open a form from TreeViewMenu.

case "Edit user":
                        {
                            EditUser form = new EditUser();
                            form.Text = "Edit user ";
                            form.MdiParent = this;
                            if (!KidsOpen(form))
                            {
                                form.Show();
                            }
                            else
                            {
                                SetActiveUserForm(form);
                            }
                            break;
                        }

there i call a method "KidsOpen" to determine if a form is open

public bool KidsOpen(Form FormName)
        {
            Form[] childform = this.MainDockingManager.MdiChildren;
            if (this.MainDockingManager.MdiChildren.Length == 0)
            {
                return false;
            }
            else
            {
                foreach (Form Myform in childform)
                {
                    if (Myform.Name == FormName.Name)
                    {
                        Myform.BringToFront();
                        return true;
                    }
                }
                return false;
            }
        }

if a form is open I want to set the form active (the form is inside a document pane in docking manager)

this is how i do that:

        public void SetActiveUserForm(Form form)
        {
            foreach (DocumentPane pane in this.MainDockingManager.Documents)
            {
                if (pane.MdiChild.Name == form.Name)
                {
                    this.MainDockingManager.SetDocument(pane);

                    if (this.UsersDockPanel.DockState != DockState.AutoHide)
                    {
                        this.UsersDockPanel.DockState = DockState.AutoHide;
                    }
                    else
                    {
                        this.MainDockingManager.AutoHidePanel.Hide();
                        pane.Activate();
                    }
                }
            }
        }

Now, all this methods work IF the "EditUser" form is NOT open, otherwise not. I have 3 different ways to edit user.
1. Menu item Edit user (se first code ex) (From MdiParent form)
2. GridView with all(or filtered) user list, the double click selects user to edit (From USerForm, Another child form)
3. Context menu in gridView with Edit user menu item.  (From USerForm, Another child form)

This is the methods witch handles click event of the grid

               private void usersGrid_CellDoubleClick(object sender, GridViewCellEventArgs e)
        {
            string name = this.usersGrid.MasterGridViewInfo.CurrentRow.Cells["Username"].Value.ToString();
            EditUserFromGrid(name);
            //MessageBox.Show(name);
        }

witch calls this method to open Edit user form:

private void EditUserFromGrid(string username)
        {
            MainAdmin parent = (MainAdmin)this.ParentForm;

                if (username != null)
                {
                    EditUser form = new EditUser(username);
                    form.Text = "Edit user";
                    form.MdiParent = parent;// mdiForm;// main;
                    if (!parent.KidsOpen(form))
                    {
                        form.Show();
                    }
                    else
                    {
                        parent.SetActiveUserForm(form);
                        form.UserNameToEdit = username;
                        form.Update();
                    }
                }

        }

All methods work if the Edit User form is NOT already open...

In debug mode the Text property of the combo box is the selected user (no matter witch method I use) but the combo box doe's not change it's value...it only gets "marked" (like when you drag a mouse pointer over text ind copy it)

help.....


0
Comment
Question by:ize_man
  • 5
  • 4
9 Comments
 
LVL 18

Expert Comment

by:Priest04
ID: 22964022
ize_man, from what I have seen (a quick watch on your code), this is not the right approach. Tou should first check if form is loaded, and only if not to create it. So your code should be like this
case "Edit user":
{
    EditUser frm = KidsOpen("EditUser") as EditUser;
    if (form == null)
    {
        form = new EditUser();
        form.Text = "Edit user ";
        form.MdiParent = this;
        form.Show();
    }
    else
    {
        SetActiveUserForm(form)
    }
    break;
}
 
public Form KidsOpen(string formName)
{
    foreach (Form Myform in this.MainDockingManager.MdiChildren)
    {
        if (Myform.Name == formName)
        {
            Myform.BringToFront();
            return MyForm;
        }
    }
 
    return null;
}
 
private void EditUserFromGrid(string username)
{
    MainAdmin parent = (MainAdmin)this.ParentForm;
 
    if (username != null)
    {
        EditUser form = KidsOpen("EditUser") as EditUser;
        if (form == null)
        {   
            form = new EditUser(username);
            form.Text = "Edit user";
            form.MdiParent = parent;// mdiForm;// main;
            form.Show();
        }
        else
        {
            parent.SetActiveUserForm(form);
            form.UserNameToEdit = username;
            form.Update();
        }
    }
}

Open in new window

0
 

Author Comment

by:ize_man
ID: 22973860
Hi Guru
I like your solution :-) but the result is still the same. My Edit User form does not Update or Refresh so the user name in Edit user combo box does not change if the form is already open..the selected text simply get marked.

When i debug my code this set's the doc pane that contains the open EditUser form

             parent.SetActiveUserForm(form);

            form.UserNameToEdit = username; //IGNORE THIS (this is a property in EditUser form)

            form.Update(); //THIS DOES NOT SEEM TO WORK

I can't se my form.Update() (have also tried Refresh()) run at all... I believe that i need some code there to update my EditUser form..

Any idea?

0
 
LVL 18

Expert Comment

by:Priest04
ID: 22975341
The reuslt visually looks the same, you now do not create objects that you dont use later. But for the updating part, you do. :) Refresh method will just repaint it, it will not reload data in it. The solution depends on what exactly are you trying to achieve.

If I understood you correctly, you need to update some user info. You have users displayed in some control, you select a user and click change and form appears with the current user details. You change some, click on save, form closes, and you want to update data on the previous form. If this is correct, then there are 2 ways to do this

1) (preffered one) on the form that is used to change user data, have some public property (of User type)

User _userDetials;

public User UserDetials
{
    get{return _userDetials;}
    set{_userDetails = value;}
}

When you load form that you change user details on, you will pass to it current user data through counstructor

public class FormUserDetials
{
    public FormUserDetials(User userDetails)
    {
        _userDetials = userDetials;
        // use data from _userDetials to fill controls with data
    }

 After you save changes, you will pass new data to )userDetials object. This data can be later read on the form that lists all users. Example code would like something like this:

// on the form that displays list, user clickd on a button to change user
FormUserDetials frm = new FormUserDetials(new User(userID, userName, userAddress.... etc));
frm.ShowDialog(); // the code execution stops here until the user clicks on a save button
// this is the place where we can read changed data, and update of controls manually
User user = frm.UserDetails;
// now use user object's data

this method is good if you can execute formDetials modal, and is preffered one, since you don't reload data unnecessary from database. User class is a class that represents data from user table in your database.

2) this approach is used when you have two forms that are displayed modaless. You would need to have some sort of a class that all forms will monitor for changes. Examples

public class Semaphore
{
    public static userChanged(Form frm)
    {
        // this method should be called when user is changed on any form
        // example, in FormUserDetails, after you have updated data to database, you will call this method
        // here you will need to notify all other forms that need to update data for users, if they contain any
        // so you will notify only forms that need to be notified
        foreach (Form f in Global.Forms)
        {
            if (f.Name == "SomeForm1")
            {
                ((SomeForm1)(f)).UpdateUsers = true;
            }
            else if (f.Name == "SomeForm2")
            {
                ((SomeForm2)(f)).UpdateUsers = true;
            }
        }
    }
}

as you can see, on each form that you want to reload data yo need to have property called UpdateUsers, where you will call method to update data.

bool _updateUser;

public bool UpdateUser
{
    get { return _updateUser;}
    get { _updateUser = value;}
}

and in the Form_Activate event, you will use this code

if (_updateUser) UpdateUserMethod();

and somewhere in the form have that method to reload data from database

public UpdateUserMethod()
{
    // code to reload data from database
    // after you have done make sure you set _updateUser to false, so next time you activate this form update is not executed
    _updateUser = false;
}

I know this all sounds hard, but I guess you understood the mechanism for this. :)
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:ize_man
ID: 22975548
Hi Guru

Yes, this is just about what I want to do...but I thought it might be a simpler way to do it..

I have a EditUser form with bindingsource and tableadapter witch binds to a dataset.. on that form i have a combobox where i select the user to edit...when i have selected a user the form displays all relevant user information...all controls (labels, textboxes etc) are bound to the same bindingsource control...

Now I have a separate form witch contains a grid with all users (and some filtering possibilities) where i can by double clicking on a single row (single user) select the user and open the EditUser form where my combobox has the user I selected in the grid selected and displays all relevant user information...now I can do same task by right clicking on the grid and select Edit user from my context menu...this works fine unless the EditUser form already is open :-(

I pass the "Username" as a string into the form constructor as a parameter...

Any idea or do I have to rewrite all my code to do it the way you wrote in you previous post.
0
 
LVL 18

Expert Comment

by:Priest04
ID: 22975672
I am not following you here. You say you have 3 forms? EditUserForm, FormWithGrid, UserDetailsForm.

>> this works fine unless the EditUser form already is open :-(

How do you update a form that contains grid, for example, if it is already opened? From the above statement, it seems that you are able to update data on this form?

If you have several forms that you need to update, you will need to use method2 I have provided, its not gonna be easier than that.

The code you are asking is not easy to write from my perspective, and is time demanding, so you will have to do it yourself. I have posted the guideline how to do so, which I believe contains enough information.
0
 

Author Comment

by:ize_man
ID: 22976260
Hi Guru

I don't want you to write the code for me...that's beyond forum help from my perspective.

No, I only have two forms..
1 UserForm (Witch contains grid with all users)
2. EditUser form (Witch contains detailed user information)

both forms have a bindigsource as a datasource from a dataset

If EditUser form is NOT already open in MDI parent everything works fine.. I can double click the grid and select "Edit user" item from my context menu to open EditUser form with the user i have selected in the grid.

On top of the EditUser form i have a combobox where i select user to edit..this selection set's values of all other controls on that form...so that's the only control i need to update (along woth Refresh() method)

But if the form already is open the constructor on EditUser form does not run since the form already is open. I pass the parameter for the user trough the constructor when i open the form from the beginning.

public EditUser(string user)
        {
            InitializeComponent();

            //Fill dataSet
            this.usersTableAdapter.ClearBeforeFill = true;
            this.usersTableAdapter.FillUsers(this.duoDataSet.Users);

            if (user != null)
            {
                    this.cbSelectUser.SelectedItem = user;
            }
            else
            {
                this.cbSelectUser.Text = "Select user to edit";
                this.cbSelectUser.SelectionLength = this.cbSelectUser.Text.Length;
                lblErrorMessage.Text = "No user has been selected for editing";
                lblErrorMessage.Visible = true;
            }
        }  

I do not need to update the user anywhere else except on the EditUser form...I simply want to display the user information when i select the user from the grid on UserForm.
This is the method i user when I double click ot select Edit user from context menu:

        private void usersGrid_CellDoubleClick(object sender, GridViewCellEventArgs e)
        {
            string name =    this.usersGrid.MasterGridViewInfo.CurrentRow.Cells["Username"].Value.ToString();
            EditUserFromGrid(name);
            //MessageBox.Show(name);
        }

it call this method:

        private void EditUserFromGrid(string username)
        {
            MainAdmin parent = (MainAdmin)this.ParentForm;

            if (username != null)
            {
                EditUser form = parent.KidsOpen("EditUser") as EditUser;// parent.KidsOpen("EditUser") as EditUser;
                if (form == null)
                {
                    form = new EditUser(username);
                    form.Text = "Edit user";
                    form.MdiParent = parent;// mdiForm;// main;
                    form.Show();
                }
                else
                {
                    parent.SetActiveUserForm(form);//THIS SET'S AND DISPLAYS THE DOC PANE THAT CONTAINS EDITUSER FORM IN MDI PARENT FORM
                    form.UserNameToEdit = username; //NO NEED FOR THIS
                    form.Update();
                }
            }
        }

//SET'S DOC PANE ACTIVE THAT CONTAINS EDITUSER FORM (on parent form)
        public void SetActiveUserForm(Form form)
        {
            foreach (DocumentPane pane in this.MainDockingManager.Documents)
            {
                if (pane.MdiChild.Name == form.Name)
                {
                    this.MainDockingManager.SetDocument(pane);

                    if (this.UsersDockPanel.DockState != DockState.AutoHide)
                    {
                        this.UsersDockPanel.DockState = DockState.AutoHide;
                    }
                    else
                    {
                        this.MainDockingManager.AutoHidePanel.Hide();
                        //form.Refresh();// Activate();
                        pane.Activate();
                    }
                }
            }
        }

I hope you understand what I mean...it's a bit confusing. Basically I need to update the combobox on the EditUser form that already is open...and refresh the form with that value.

Regards
0
 
LVL 18

Accepted Solution

by:
Priest04 earned 2000 total points
ID: 22979485
I am a little confused why do you have 2 forms that both contain user list: one through datagridview and one through combobox. Usually the scenario is: main form with grid, and another form with textboxes that contain detailed information. 2nd form is not shown always, but only when user is updating data.

Since you choose different approach, a quick solution is to refill the dataset (altough I dodont aprove this method). So the code in the contructor for EditUser form that fills dataset should be moved to another method, like

public EditUser(string user)
{
    InitializeComponent();
    GetData(user);
}  

public void GetData(string user)
{
    //Fill dataSet
    this.usersTableAdapter.ClearBeforeFill = true;
    this.usersTableAdapter.FillUsers(this.duoDataSet.Users);
   
    if (user != null)
    {
        this.cbSelectUser.SelectedItem = user;
    }
    else
    {
        this.cbSelectUser.Text = "Select user to edit";
        this.cbSelectUser.SelectionLength = this.cbSelectUser.Text.Length;
        lblErrorMessage.Text = "No user has been selected for editing";
        lblErrorMessage.Visible = true;
    }
}

and now you can call this method, instead of calling Refresh() method, like you have tried. So, if forms do not exist, you create it through its contructor (you do not call GetData method, contructor will do it for you), if form already exist, then you dont need to create a form, just get reference to it, and call GetData(userName) method.
0
 

Author Comment

by:ize_man
ID: 22980064
Hi Guru

The reason I have this method is that the user can choose EditUser form from a menu at the same time the UserForm has a shortcut trough the double click and context menu to EditUser form. The app I am writing is a admin part of a bigger solution. In this part the admin manages all users of the "User" part of the app.
I appreciate your effort to help me and just so you know....it worked :-) ...and to follow your advise i will try the solution you preferred....just to learn. I am not so experienced yet but new challenges is a good thing.  

Once again, thank you for all the help. Problem solved.
0
 
LVL 18

Expert Comment

by:Priest04
ID: 22980755
You are welcome.
0

Featured Post

Visualize your virtual and backup environments

Create well-organized and polished visualizations of your virtual and backup environments when planning VMware vSphere, Microsoft Hyper-V or Veeam deployments. It helps you to gain better visibility and valuable business insights.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Many of us here at EE write code. Many of us write exceptional code; just as many of us write exception-prone code. As we all should know, exceptions are a mechanism for handling errors which are typically out of our control. From database errors, t…
Today I had a very interesting conundrum that had to get solved quickly. Needless to say, it wasn't resolved quickly because when we needed it we were very rushed, but as soon as the conference call was over and I took a step back I saw the correct …
Integration Management Part 2
Look below the covers at a subform control , and the form that is inside it. Explore properties and see how easy it is to aggregate, get statistics, and synchronize results for your data. A Microsoft Access subform is used to show relevant calcul…
Suggested Courses

807 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question