Link to home
Start Free TrialLog in
Avatar of ize_man
ize_manFlag for Sweden

asked on

Refresh form when already open and it's combo box

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.....


Avatar of Priest04
Priest04
Flag of Serbia image

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

Avatar of ize_man

ASKER

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?

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. :)
Avatar of ize_man

ASKER

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.
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.
Avatar of ize_man

ASKER

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
ASKER CERTIFIED SOLUTION
Avatar of Priest04
Priest04
Flag of Serbia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of ize_man

ASKER

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.
You are welcome.