3

Essentially I need the same thing that Form.ShowDialog() offers, but with a UserControl.

Inside a winform, I load a UserControl, which should allow a user to select an item from a list, and return it back to the caller.

For example:

var item = myUserControl.SelectItem();

Obviously, returning from a control's method is very simple. But how can I make it wait until user performs the required action with the control?

I can subscribe to an event of the control, but this path is not ideal.

Put simply, I want a UserControl's method to return after user clicks a specific button on it.

SharpAffair
  • 5,558
  • 13
  • 78
  • 158
  • Hmm, how exactly is your design? E.g. what would be wrong with a form popup like @pm_2 suggests? What should be disabled when you show your usercontrol? – Johny Skovdal Jun 27 '13 at 18:27
  • i assume you want Blocking UI style .by the way it looks great . on net u can find examples for jscript . but we once did for our front end window – qwr Jun 27 '13 at 18:30
  • 1
    It's a design like on mobile phones. The app has multiple pages (built as UserControls). One of the pages serves as a widget for selecting some values. User clicks a button to confirm the selection. After the value is selected in the UserControl, the code in the parent form should process it. So essentially the form loads a temporary UserControl just to allow user selecting a value. – SharpAffair Jun 27 '13 at 18:34
  • what i suggested is the same like modal dialog .for example we were doing it make user adjust microphone level each time when program encountered low volume . think this solution is what you need . but you know better of course – qwr Jun 27 '13 at 18:40
  • @LoveDotNet why don't you use MDI form? And treat your pages (UserControl) as normal children Forms instead. – King King Jun 27 '13 at 23:18
  • The only way that you're going to know when the user clicks a button on the contained UserControl is through an Event. I've provided an example in my answer which . – Brad Rem Jun 28 '13 at 14:11

3 Answers3

5

Simply put, a UserControl is really just a custom control and just like you drop a TextBox or a ListBox on your WinFrom, you drop your UserControl on the form.

Treat your UserControl just like you would treat any other control, like TextBox or ListBox.

So, just like you get the value from a TextBox through TextBox.Text or the SelectedValue or SelectedItem from a ListBox, you would call a method from your UserControl to return the SelectedItem.

Often times when the OK button is clicked or the form is closed is when in your code you would go through each of your form's controls getting their values. Presumably, you would do some validation to make sure proper values were entered, too.

Therefore, when your form is accepted is when you would call your UserControl's method to get the selected item. You don't have to subscribe to an event to wait for that to happen. Again, just treat it like you would treat a normal ListBox.

EDIT:

Knowing now more about the nature of your question this is my answer:

Say you have a UserControl that looks like this:

SelectFromListUserControl

In the code behind you are going to have to set up an Event to monitor when the the OK button has been clicked inside the UserControl. This event will also notify a subscriber what the choice was that the user selected in your list:

public partial class SelectFromListUserControl : UserControl
{
    public class SelectedItemEventArgs : EventArgs
    {
        public string SelectedChoice { get; set; }
    }

    public event EventHandler<SelectedItemEventArgs> ItemHasBeenSelected;

    public SelectFromListUserControl()
    {
        InitializeComponent();
    }

    private void btnOK_Click(object sender, EventArgs e)
    {
        var handler = ItemHasBeenSelected;
        if (handler != null)
        {
            handler(this, new SelectedItemEventArgs 
                { SelectedChoice = listBox1.SelectedItem.ToString() });
        }
    }
}

On your main form you will have code patterned similar to the following.

  1. There should be a routine to create or make visible this special user control.
  2. It will hook the event in the user control so that the main form will be notified.
  3. It will draw the user control.
  4. The event handler will retrieve the value selected in the user control and then clear the user control and/or bring up another user control.

    private void ShowSelectFromListWidget()
    {
        var uc = new SelectFromListUserControl();
        uc.ItemHasBeenSelected += uc_ItemHasBeenSelected;
    
        MakeUserControlPrimaryWindow(uc);
    }
    
    void uc_ItemHasBeenSelected(object sender, 
                         SelectFromListUserControl.SelectedItemEventArgs e)
    {
        var value = e.SelectedChoice;
    
        ClosePrimaryUserControl();
    }
    
    private void MakeUserControlPrimaryWindow(UserControl uc)
    {
        // my example just puts in in a panel, but for you
        // put your special code here to handle your user control management 
        panel1.Controls.Add(uc);
    }
    
    private void ClosePrimaryUserControl()
    {
        // put your special code here to handle your user control management 
        panel1.Controls.Clear();
    }
    
Brad Rem
  • 6,036
  • 2
  • 25
  • 50
  • 1
    It looks like that the OP wants user to be able to interact with his UserControl only, for some reason, modifying any info/data outside of the UserControl may cause his application to work improperly. So he wants everything to go in order. Your approach is OK in some case but that's not the case of the OP. – King King Jun 27 '13 at 23:15
  • @KingKing, I think I see now what the OP is trying to achive and have added a code sample of a pattern I think he could follow to achieve what he wants. – Brad Rem Jun 28 '13 at 14:08
0

Embed it in a form and call the form modally (ShowDialog)?

Paul Michaels
  • 16,185
  • 43
  • 146
  • 269
  • I need the control inside the main form. My idea is to have an application with a single form, but multiple different pages that are loaded on demand. – SharpAffair Jun 27 '13 at 18:24
  • Then you have no choice but to enable / show the other controls on an event from the user control. – Paul Michaels Jun 27 '13 at 18:25
0

But how can I make it wait until user performs the required action with the control?

The question is more about how to wait for the user to select item and click OK button without blocking entire user interface.

The answer is simple: Async/Await feature.

private readonly SelectCompletionSource as new TaskCompletionSource(of ResultType)

public async function SelectItemAsync() as ResultType

    me.Visible = true

    return await SelectComplectionSource.Task
end function

public function OK() as boolean

    me.Visible = false

    dim Result = me.SelectedItem

    SelectComplectionSource.
        SetResult(Result)
end function

To get an Item one calls

dim Item = await UserControl.SelectItemAsync

UserControl is shown to the user without blocking user interface. The selection task is started but paused until the result is ready.

By clicking OK button, user invokes OK function that queries selected item and makes selection task into completed state.

Lightman
  • 1,078
  • 11
  • 22