-1

I have a Windows Desktop App with an auto-update method implemented. I want to show a custom Form (because I need to change the button texts) asking the user if he or she wants to download the new version or not when a new update is detected and I want to "block" all input actions in the Desktop App until the user has made his selection.

After reading Form.ShowDialog() documentation and several topics here saying "ShowDialog() is not making my windows modal" and several answers replying "You need to properly set the owner" I still don't understand how to set this owner. Of course if I make two forms and the first one shows the second, I can "block" the first one doing:

secondForm.ShowDialog(firstForm);

But I don't know how to make that the firstForm blocks all the application to prevent the user using a deprecated version of it.

I tried several approaches like getting the current id process (or trying to get it) and convert it to IWin32Window. But nothing seemed to work.

If you need it, I add here the code I'm using:

 FormAsk  formAsk = new FormAsk (param1, param2);
 formAsk.StartPosition = FormStartPosition.CenterParent;
 formAsk.TopLevel = true;
 formAsk.TopMost = true;
 formAsk.DialogResult = formAsk .ShowDialog();
 if(formAsk.DialogResult.Equals(DialogResult.OK))
 {
      // do stuff
 }
 else
 {
      // do other stuff
 }

I've also seen lots of solution implementing:

myForm.ShowDialog(this);

But VS start's crying because the types are not compatible. I'm using a MVVM pattern so I can't just set a Form as an owner because I don't have a main form. Just views in .xaml and views controllers in c#.

Edit: I would like to add few comments I learned after facing this issue that may help to understand better my situation.

The main method of the program executes the following:

[STAThread]
    static void Main()
    {
        //stuff
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            try
            {
                //stuff
                STAApplicationContext context = new STAApplicationContext();
                Application.Run(context);
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message, Localization.Strings.error_popup_title);
                Application.Exit();
            }
        }
    }

And this context is the one that generates the service layer and views manager of the application. If I display the Forms in the service layer, showDialog() method can not "block" the input in the views but if I display them from the views (generated and handled by the view manager) i can. There's a communication between views and service, because actions triggered in the views have as consequence a service method call, but in this case the communication I want is the opposite: the service calling the methods in the view controllers to display the Forms by showDialog().

  • You need to capture the exit method of form to prevent closing and so nothing else executes. See my two form project : https://stackoverflow.com/questions/34975508/reach-control-from-another-page-asp-net?force_isolation=true – jdweng Feb 16 '22 at 15:30

3 Answers3

1

You need to pass an instance of the IWin32Window interface to the ShowDialog method.

IntPtr myWindowHandle = IntPtr(parent.Handle);
IWin32Window w = Control.FromHandle(myWindowHandle);
Eugene Astafiev
  • 47,483
  • 3
  • 24
  • 45
  • I'm using a MVVM pattern so I can't just set a Form as an owner because I don't have a main form. Just views in .xaml and views controllers in c#. – BugsAreEverywhere Feb 17 '22 at 10:03
  • Is the view displayed anywhere? – Eugene Astafiev Feb 17 '22 at 10:05
  • It is. In fact there's an Application.run that defines a main thread where views are displayed. The problem is accessing this context in order to call views controller and display there the Forms to be able to block the input in the views – BugsAreEverywhere Feb 18 '22 at 10:40
  • See [Finding the handle to a WPF window](https://stackoverflow.com/questions/1556182/finding-the-handle-to-a-wpf-window) – Eugene Astafiev Feb 18 '22 at 10:44
0

Do your Stuff in your first Form and whatever button you press to create your second Form just go like this. (Pseudo Code)

button1_click()
{
   Form2 = new Form() 
   Form2.Owner = this;
}

and now from your Form2 you can talk to your Owner with this.Owner.Visible = false for example.

Thats how you make the Owner if thats what you asked for.

Nael
  • 27
  • 4
0

Thanks those who tried to help with your replies. However, although your answers probably will work in other circumstances, mine where a bit different.

Finally I achieved to solve it, I needed to do the handle with Forms in a higher level of abstraction. The information managed was retrieved from an asynchronous task so I couldn't use there a showDialog method and block the MainWindow of the application. Instead I did several threads, wait them and eventually show dialogs when I needed. It's not the best approach, but given the context is the only thing I could do.