wpf mousecapture being force released immediately - wpf

I'm building a user control that includes a flyout panel.
When I click the button to open the panel I'm trying to capture the mouse so that I can detect if the user clicks off the flyout panel so I can close it.
But right after I capture the mouse, I get a lost mousecapture event and I can't detect the clicks outside of the panel.
here is where I detect the straight open close click
private void Grid_MouseUP(object sender, MouseButtonEventArgs e)
{
if (indicatorVM != null)
{
if (indicatorVM.SettingsFlyoutVisibility == Visibility.Collapsed)
{
doRelease = false;
indicatorVM.SettingsFlyoutVisibility = Visibility.Visible;
bool result = this.CaptureMouse();
result = Mouse.Capture(this, CaptureMode.SubTree);
}
else
{
doRelease = true;
indicatorVM.SettingsFlyoutVisibility = Visibility.Collapsed;
this.ReleaseMouseCapture();
}
}
}
If I wire into the capture lost event, it's hit immediately after the flyout opens. When I check the result variable, regardless of how I capture the mouse, the result is true, so it appears to be working correctly.
Any ideas?

First, try an UpdateLayout right after setting indicatorVM's visibility to Visible, before you capture the mouse. This will avoid having the layout change after you capture the mouse, which is probably what is stealing the capture from you. My second suggestion is to slightly postpone the capture with a Dispatcher Invoke, like this:
Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, (Action)delegate()
{
bool result = this.CaptureMouse();
result = Mouse.Capture(this, CaptureMode.SubTree);
});
The capture will then be after the layout consequences.

Related

WinForms form partially loses focus after disabling all controls

The focus rectangle and textbox caret are lost after disabling all controls, then enabling them again (vs2012 / .NET Framework v4.5).
To reproduce the issue, just create a WinForms application project, add a button and a textbox in the form, then use this code to disable and enable both controls in the button click event:
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
textBox1.Enabled = false;
button1.Enabled = true;
textBox1.Enabled = true;
}
You may cycle between the textbox and the button using Tab/Shift+Tab as expected, until you press the button.
After that, the focus is partially lost (its weird). You can still use Tab/Shift+Tab and arrows to nagivate between the controls, and press Enter to active the button, but you cannot type in the textbox, nor use the space key to press the button. The textbox caret and the button focus rectangle are not displayed anymore. Changing focus to another application then returning to this form will fix the focus issue.
This issue does not happen if you don't disabled at least one control that is able to receive focus. Also the focus behavior is restored by disabling and enabling again the form, like this:
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
textBox1.Enabled = false;
button1.Enabled = true;
textBox1.Enabled = true;
this.Enabled = false;
this.Enabled = true;
}
I was trying to disable all the controls of a more complex form at the start of a task, so the task would enable again all controls after finishing, to prevent user input during the processing, but without locking the UI thread. I thought it was related to the cross-thread invoke calls, but I found this issue happens even with all code running on UI thread.
This undesired behavior can be fixed by calling the form Focus() method:
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
textBox1.Enabled = false;
button1.Enabled = true;
textBox1.Enabled = true;
this.Focus();
}
The ActiveControl is not changed after calling Focus(), so this works very well for me.

WPF: How to Hide a modal dialog box without destroying it? (its DialogResult)

I've got a modal dialog box and (when user presses its OK button) I want to hide it, show another modal dialog box (MessageBox for example) and then show it back again. My problem is that when the dialog is hidden, its DialogResult gets false and of course its getting closed right after the button's handler method ends. I've even tried to set Opacity to 0 instead of Hide() but that doesn't work at all (it's still visible).
Is there a way to hide a modal dialog box for a moment without closing it?
Workaround that is working for me:
To prevent the window from being closed once you set the DialogResult, create your own DialogResult instead:
public new bool DialogResult;
Now you can still set the variable and choose Hide() instead of Close().
So all the places where DialogResult is set I add a
Hide();
So i looks like this:
DialogResult=true;
Hide();
or
DialogResult=false;
Hide();
That way I can do a new ShowDialog() again.
So if I need to reopen the window until the content is correct (if validation happens after closing), it would look something like this:
public void ShowDialog()
{
var dialog = new MyDialog();
bool ok = false;
while (!ok)
{
dialog.ShowDialog();
if (dialog.DialogResult)
{
ok = DoSomeValidation();
}
else
{
ok = true;
}
}
}
This does not deal with the result but see how to return data from a Page
PageModal is a Page
You use NavigationWindow for the modal part
public partial class MainWindow : Window
{
private PageModal pageModal = new PageModal();
public MainWindow()
{
InitializeComponent();
}
private void btnLaunchModal(object sender, RoutedEventArgs e)
{
NavigationWindow navWindow = new NavigationWindow();
navWindow.Content = pageModal;
navWindow.ShowDialog();
}
}
Ok, the opacity IS working. I just had it blocked by finished animation (with HoldEnd behavior) and I didn't knew about it. So, if anyone has the same problem and needs to hide a modal window, the Opacity = 0; is the solution.

Avoid radcombobox suggest list from being collapsed

I have a RadDropDownList in suggestappend mode and a usercontrol as keyboard, this have buttons with ControlStyles.Selectable = false. the MouseUp event fires a SendKeys.Send(key).
The thing is when I focus in the RadDropDownList and write with my keyboard (UserControl) the suggest list appears for a milisecond and desappear.
I tried to control the popup event but it seems to have nothing to do with the suggest list.
how can i keep it opened showing suggestions until user leaves the RadDropDownList?
Here is how to access the auto complete suggest popup and cancel the closure of the popup:
radDropDownList1.DropDownListElement.AutoCompleteSuggest.DropDownList.PopupClosing += DropDownList_PopupClosing;
. . .
void DropDownList_PopupClosing(object sender, Telerik.WinControls.UI.RadPopupClosingEventArgs args)
{
args.Cancel = true;
}

How do prevent a WPF text box inside a combo from reacting to right mouse clicks?

I creating a custonmized box class (inherits from ComboBox). I don't want the text box to react to right mouse clicks. I can get rid of the context menu by setting this to null in ApplyTemplate, but right mouse clicks move the cursor. I tried hooking up PreviewMouseRightButtonDown in ApplyTemplate and setting Handled to True, but the event still gets through which is strange as it seems to work for the left click.
The cursor actually moves when the mouse button is released, so you want mark the MouseRightButtonUp event as handled. You could override OnMouseRightButtonUp:
protected override void OnMouseRightButtonUp(MouseButtonEventArgs e)
{
base.OnMouseRightButtonUp(e);
e.Handled = true;
}
Or you could attach a class handler to the MouseRightButtonUp event to mark it as handled:
static MyComboBox()
{
EventManager.RegisterClassHandler(
typeof(MyComboBox),
MouseRightButtonUpEvent,
new MouseButtonEventHandler(MyComboBox_MouseRightButtonUp));
}
private static void MyComboBox_MouseRightButtonUp(
object sender, MouseButtonEventArgs e)
{
e.Handled = true;
}
That will also prevent the context menu from being created without you having to set it to null explicitly.

Winforms - why does a "Show()" after a system tray double click end up in my app minimized?

Winforms - why does a "Show()" after a system tray double click end up in my app minimized?
How do I ensure Inthe notifyicon double click event that my hidden main form comes back visible as normal, not minimized (nor maximised for that matter too)
I would guess that you put your application in tray on minimize action. In that case, Show just restores visibility.
Try adding form.WindowState = Normal before Show().
Hiding your form with the NotifyIcon is often desirable so your app starts in the tray right away. You can prevent it from getting visible by overriding the SetVisibleCore() method. You also typically want to prevent it from closing when the user clicks the X button, override the OnFormClosing method to hide the form. You'll want a context menu to allow the user to really quit your app.
Add a NotifyIcon and a ContextMenuStrip to your form. Give the CMS the Show and Exit menu commands. Make the form code look like this:
public partial class Form1 : Form {
bool mAllowClose;
public Form1() {
InitializeComponent();
notifyIcon1.DoubleClick += notifyIcon1_DoubleClick;
notifyIcon1.ContextMenuStrip = contextMenuStrip1;
showToolStripMenuItem.Click += notifyIcon1_DoubleClick;
exitToolStripMenuItem.Click += (o, e) => { mAllowClose = true; Close(); };
}
protected override void SetVisibleCore(bool value) {
// Prevent form getting visible when started
// Beware that the Load event won't run until it becomes visible
if (!this.IsHandleCreated) {
this.CreateHandle();
value = false;
}
base.SetVisibleCore(value);
}
protected override void OnFormClosing(FormClosingEventArgs e) {
if (!this.mAllowClose) { // Just hide, unless the user used the ContextMenuStrip
e.Cancel = true;
this.Hide();
}
}
void notifyIcon1_DoubleClick(object sender, EventArgs e) {
this.WindowState = FormWindowState.Normal; // Just in case...
this.Show();
}
}

Resources