How to open modal wpf window scoped to a tab item - wpf

I have a use case where we have an application with a tabcontrol with 2 or more tab items . I want to be able to open a modal Window (using Window.showDialogue()) so the user is blocked to do any thing else within the active tab item from where the modal window was opened . But should be able to click on other tab item and continue to do the work .
Currently Window.showDialogue() completely blocks all user interactions until the window is closed . Is it possible to change the scope of the blocking window to just the initiating tab item ?
As an alternative , I have a overlay design to show the popup content using the Panel.Zindex and then disable the underlying controls container . But I would prefer to do the simple way of window.showdialogue().
Any help would be appreciated.

As far as I know, here is no way to block only part of a Window when calling ShowDialog. The blocking is done at the Window level by the OS. You'll have to manually disable that tab.
Be aware that if you simply put another element on top of the tab to obscure it, the user may still be able to access the controls below by using the Tab key. You might need to set IsEnabled to false, or maybe IsHitTestVisible, depending on the how you want the application to behave.

Related

WPF - Focus second window by clicking a button

I'm creating a WPF application and I have 3 Windows (MainWindow, Window2 and Window3). When I start the project Window2 loads right after my MainWindow is loaded. And when I click a Button, Window3 opens
Window3 w3 = new Window3(this, this.window2);
w3.ShowDialog();
but I'm not able to do things (click controls etc.) in Window2, I know that ShowDialog() method is disabling other open Windows but is there a possibility to access using those controls in Window2. How could I get access to Window2's functionalities when Window3 is open?
PS.(Sorry for asking a stupid question but I'm beginner in WPF)!
You can access System.Windows.Application static class's Windows collection to have list of all currently opened windows. Then you can iterate the collection and find your window by type or some other criteria. One way would be:
var window3 = Application.Current.Windows.OfType<Window3>().FirstOrDefault();
Edit:
In comments to the question you stated that you were opening window using w3.Show() method. That opens window in non modal way. While after editing the question w3.ShowDialog() opens the window in modal way.
You can learn more about modal windows at MSDN
A modal dialog box is displayed by a function when the function needs additional data from a user to continue. Because the function depends on the modal dialog box to gather data, the modal dialog box also prevents a user from activating other windows in the application while it remains open.
So to be able to switch focus between windows they should be non modal and opened using Show method instead of ShowDialog.

Show Winforms Contextmenu over ChromiumWebBrowser

I'm working on a Winforms project that uses CefSharp as a Gui. For several reasons I would like to implement a custom context menu using the Winforms ContextMenu class; rendering the menu in Html or customizing the ChromiumWebBrowser's context menu (using CefSharp.IContextMenuHandler) are not an option.
The context menu it triggered by Javascript code that calls a method on a .net object I passed to RegisterAsyncJsObject; the default context menu is prevented using Javascript. I'm invoking the method call on the Gui thread, because the call over the "javascript bridge" to the registered object comes from a different thread.
My problem: when manually showing the Winforms context menu over the CefSharp.WinForms.ChromiumWebBrowser the context menu does not get the keyboard focus (e.g. selecting items with the arrow key doesn't work nor can I close the contextmenu using Esc); instead the keyboard focus remains with the ChromiumWebBrowser control. And, if I click on the ChromiumWebBrowser's control area the context menu doesn't close either. I can only close the context menu by selecting an item with the mouse or clicking on another control within the form (in which the ChromiumWebBrowser is contained) or somewhere completely else (e.g. desktop or another application).
If I trigger the context menu from elsewhere in my code - ultimately using the same method that calls myContextMenu.Show() - the context menu gets the keyboard focus as desired. But one problem still remains: it doesn't close when I click within the ChromiumWebBrowser control.
I haven't used IFocusHander, IContextMenuHandler, IKeyboardHandler - should I?
I'm using CEF 3.2454.1344.g2782fb8, Chromium 45.0.2454.101 and .net 4.5.1.
Unfortunately extracting demo code isn't reasonably possible.
Anyone any ideas?
EDIT1:
After reading the comments, I decided to describe the code flow more precisely:
When right clicking Javascript sends a message to the registered .net object, containing the mouse coordinates. The default context menu is prevented by setting preventDefault on the MouseEvent arguments of the ContextMenu event.
The registered .net object receives the messages and calls windowForm.Invoke(Sub() ... ), because the message is not received on the Main/Gui thread, but must be processed there for the context menu to appear correctly.
The contextmenu is created and assigned to the ContextMenuStrip property of the UserControl that contains the actual ChromiumWebBrowser control.
It is displayed using ContextMenuStrip.Show(location) method.
Issues:
The context menu has no keyboard-focus.
All mouse events appear to be "swallowed" by the ChromiumWebBrowser: clicking there does not close the context menu.
Opening the context menu identically except for using a different "trigger" works fine, except for the 2nd issue.
In the end the solution is simple; everything works as implemented and desired, if the following steps are added:
Before showing the context menu disable the UserControl with the ChromiumWebBrowser and set the focus to the owning form; something like this:
Private Sub showContextMenu(position As Point)
Me.ctrlCefBrowser.Enabled = False
Me.Focus()
myContextMenu.Show(position)
End Sub
That takes the focus away from the ChromiumWebBrowser, giving the context menu a chance to respond to the keyboard inputs. And also, by disabling the control, the mouse events are not "swallowed" anymore so clicking on the browser area causes the context menu to go away again.
Then, finally, add an event handler to the context menu to re-enable the browser control again:
Private Sub myContextMenu_Closed(sender As Object, e As ToolStripDropDownClosedEventArgs) Handles myContextMenu.Closed
Me.ctrlCefBrowser.Enabled = True
Me.ctrlCefBrowser.Focus()
End Sub
That did the trick for me, now I have a fully customizable Gdi context menu for my webbrowser control :o)
Note:
A similar problem arises when using other menus as well, e.g. in a main menu or tool bar: clicking on the ChromiumWebBrowser control will not close the menu (because the mouse event is also "swallowed"). The same solution can be applied: when opening a drop down menu deactivate (Enabled = False) the web browser control. And when it closes, reactivate it. For my menus I used a derived class (Inherits ToolStripMenuItem) that adds listeners to the according events. That takes care of the problem in a global and simple way.
EDIT:
The proposed solution above left the problem that the click on the disabled browser control closed the menu as intended, but got lost, i.e. the browser couldn't process it. My current workaround now is:
Do not disable the browser control.
Using the openening events of menu items and context menus, keep track of which menu is currently open.
When the browser receives the focus (obtainable by intercepting WndProc messages) close the opened menu.
Implementing the actual solution caused some headaches in the details, but maybe that helps someone along anyhow...

WPF menu and multitouch

I have a menu that is implemented in a way that when a menu item is pressed, a popup containing it's sub-items is open.
When running with touch screen, occasionally user touches 2 menu items at the same time with his fingers - and this leads to one of the menuitems have a touch capture which is not released until another window gets focus, making the app seem stuck.
How can I prevent such a case?
thanks
You could use a queue that contains delegates:
When triggering a command, add the delegate to the queue.
Then grab the first delegate of the queue and flush it afterwards.
Now you only have 1 "command".
I found the cause for the problem: the popup used to display submenu items had StaysOpen set to false.
This causes the Popup to capture input so it can know when to close itself once a click was made outside its boundaries.
Setting its StaysOpen property to True fixed the issue.

WPF + PRISM - show modal popup window with controls in it?

I am following the 'Stock Trader RI' example by the Prism team,
but it does not address this exactly :
I have a Shell with a Main Region in it.
In this shell I have some filter fields and a grid.
When I press on a button - I would like to load a screen that allows me to change the filters,
and then press 'Save'. This would then call a service to update the fields, and close the pop-up.
Here is an illustration of the 'Shell' before pressing the button (left) and after (right) :
Problems are :
The 'Stock Trader RI' sample app only uses a modaless dialog popup. I need a MODAL pop-up (background will continue to refresh, but user will not have access to it as long as pop-up is active).
Need to have Silverlight-like effect when pop-up shows, meaning - 'Shell' needs to appear 'disabled' (like a gray mask over it).
Pop-up window should have no 'X' button and no 'minimize' or 'maximize' buttons. The pop-up window should be simply a rectangle with curved-corners.
I don't think I can use a 'Notification Window' or a 'Confirmation Window' because I cannot put inside them whatever I want. This is an example with 2 fields, but the pop-up might be much more complex with tabs, and a lot of information shown to the user.
So how do I show a modal pop-up from my "WPF+PRISM" Shell-View-Model once the 'Edit' button is pressed ? (Meaning, once the 'EditCommand' is executed...)
I have found a solution here.
Basically it uses InteractionRequest and it allows me to open a window (that I can style however I want, without the 'Maximize' 'Minimize buttons), and also - I can choose for it to be Modal.
Great thing about this solution is - that I can use custom pop-ups and not only Notification or Confirmation pop-ups.
Also - I can pass information back to the class the invoked the 'InteractionRequest'.
Only thing that it doesn't solve - is that I cannot make the calling view look disabled by adding a gray semi-transparent over it ... haven't figured out yet how to do that...

When Modal Dialog is shown in WPF and a user clicks on the parent window, make the modal dialog flash, blink or shake

New Thought, Maybe I am looking at this totally incorrectly. So Here is exactly what I am trying to do in case there is another option I am not aware of.
I have a WPF app, the main window shows a smaller dialog window using ShowDialog(), when a user clicks on the parent window that showed the dialog, I need to make the dialog window, flash, shake or blink.
AresAvatar posted a link that looks like it might be able to use, but is there another option I am not aware of?
My original Question.
Mouse click event when Modal window's parent is clicked in WPF app?
I have a wpf app that shows a modal window using ShowDialog().
I would like to fire an event when the user tries to click the parent window that is now disabled.
Is it possible on the parent to receive a click event when it has shown a modal window?
When I attempted this using an interaction trigger, the events never fired on parent window.
Otherwise, what suggestions / options are there.
Thanks
No WPF events are sent under these conditions. The only Windows message I can see that gets sent is WM_WINDOWPOSCHANGING. You could check for that message, and check if the window was disabled when it occurred. Here's a good article on checking WM_WINDOWPOSCHANGING.
Edit: that link seems to be dead. Here's an example on StackOverflow of checking window messages.
I know this is an old question but I'll post my solution in case any one needs it.
Set the dialog.owner prior to calling ShowDialog().
var dialog = new DialogWindow();
dialog.owner = MainWindow;
dialog.ShowDialog();
The result is that clicking on the main window, brings the dialog window to the front and makes the dialog window flash.

Resources