views:

759

answers:

3

Hi.

I have a windows forms app where I have split different functionality into several user controls. I want each of these user controls to have an accept button.

Any best practices here?

My idèa is to detect which user control that has focus, and than set it in the parent Form.

Any other idèas?

+3  A: 

The best practice is usually to only have one accept button for your form so that its behavior is consistent. It generally would be confusing for users if hitting return caused different actions depending on which section of the form had focus. However, if you have a specialized application or users have requested this feature then I think the solution you propose would work.

Jamie Ide
+1  A: 

Jan Miksovsky has an excellent blog on UI design, and wrote an article about this very thing.

Most UI platforms allow a designer to indicate which button in a dialog should be the default button: the button that will be pressed if the user types the Enter key. The default button is generally the button the user is most likely to press next, often a button like OK that closes the dialog. In very high-traffic dialogs, you may want to consider dynamically changing the default button to save keystrokes and help speed the user's task.

The example he uses is the "Select Names" dialog in Microsoft Outlook, which changes the default button depending on what you are doing.

Jon Grant
A: 

I assume each user button is its own instance on the individual user controls?

If so then you can trap the button events on the Parent form. If you expose the individual buttons through a property you can tie into their Click events. Like all controls they have a name property so you can have one method that is called on all button click events.

Below I have a partial sample code. I have two user controls that have one button each. The button on UC1 is named "btn1" and "btn2" for UC2. I call the exposed property "ButtonOK"

public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
    }

    public Button ButtonOK
    {
        get { return btn1; }
    }
}

public partial class UserControl2 : UserControl
{
    public UserControl2()
    {
        InitializeComponent();
    }

    public Button ButtonOK
    {
        get { return btn2; }
    }
}

Now on the parent ("Form1") when it loads have a mthod that ties into the Click events of each button but it calls the same method. Inside the method I test for the "Name" property.

    public Form1()
    {
        InitializeComponent();
    }

    void Form1_Load(object sender, EventArgs e)
    {
        RegisterButtonEvents();
    }

    void RegisterButtonEvents()
    {
        userControl11.ButtonOK.Click += new EventHandler(ButtonOK_Click);
        userControl21.ButtonOK.Click += new EventHandler(ButtonOK_Click);
    }

    void ButtonOK_Click(object sender, EventArgs e)
    {
        Button btn = sender as Button;
        if (btn != null)
        {
            if (btn.Name == "btn1")
            {
                Console.WriteLine(" ButtonOK from UserControl1 was pushed. The tag is " + btn.Tag.ToString());
            }
            else if (btn.Name == "btn2")
            {
                Console.WriteLine(" ButtonOK from UserControl2 was pushed. The tag is " + btn.Tag.ToString());
            }
        }
    }

You can also user the "Tag" property of a control. This property can be very useful as it can reference objects.

You don't need to do exactly as shown but you can use any "Parent" form to get a reference to the UserControls, have them expose their Buttons, then you can do anything you want with properties and events from those Buttons (or any control for that matter).

Keep in mind that if you are tying into the click event on the user control also (in addition to the parent form), you will have to be mindful of the order in which it will enumerate through it list of delegates and execute code after the event is intiated.

Hope that helps.

John Cuckaroo
Each button is a separate instance yes. However my concern was just to set the aproperiate button as AcceptButton whenever a new usercontrol gets focus, not to catch the events. But maybe I misunderstand your answer. Thanks anyway :)
Ezombort