Winforms Databound ComboBox doesn't update when close Window - winforms

I have a combobox that is databound and updates with no issues. The problem I have is if the user types something into the combobox and then uses the [X] close button in the window without tabbing out, the data is not updated. I've been looking all over the web, but can't find any relevant help/tips. The only idea is have is to force an out of focus and maybe that would force the combobox to see the update.

Try adding the FormClosing event on your form.
The FormClosing event occurs as the form is being closed.
private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
{
//force an event to have the cbo updates fire.
txtFoo.Focus();
}
or VB.NET
Private Sub Form1_FormClosing(sender as Object, e as FormClosingEventArgs) _
Handles Form1.FormClosing
'force an event to have the cbo updates fire.
txtFoo.Focus()
End Sub
From there, you can call the method/logic to have your combobox's contents saved to your datastore.

Related

MessageBox pops up behind ComboBox drop down list, obscuring content in MessageBox

In a project I am working on, I have a ComboBox with dates that calculates the persons age depending on certain other criteria elsewhere in the application.
If the user selects a date, we pop up a notification to the user that we changed a few things on the form due to this.
As you can see in the picture, the combobox's items end up still staying on top of the messagebox when it pops up. The user can still click OK, and can move the box, but this is an odd way to present information to the user.
Is there a way to pop up the message box above this list, or hide the list before the messagebox comes up? I tried setting IsDropDownOpen, but that doesn't work.
Update: The MessageBox.Show event happens in the selection changed, which is why I figured it hadn't closed the drop down yet. How could one get around this though?
Update 2: Code I currently have goes like this. ComboBox uses a 'LostFocus' event (to handle typing and/or selecting) to call a CheckDOB method. CheckDOB is where I then show the MessageBox
Well I can't reprodouce your issue, but I believe that using the Dispatcher can help.
Try this:
VB.NET
Private Sub ComboBox_SelectionChanged(sender As System.Object, e As System.Windows.Controls.SelectionChangedEventArgs)
'Do what you need..
Me.Dispatcher.BeginInvoke(Sub()
MessageBox.Show("Message", "Caption", MessageBoxButton.OK, MessageBoxImage.Information)
End Sub)
End Sub
C#
private void ComboBox_SelectionChanged(System.Object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
//Do what you need..
Dispatcher.BeginInvoke(new ThreadStart(() =>
{
MessageBox.Show("Message", "Caption", MessageBoxButton.OK, MessageBoxImage.Information);
}));
}

Stop comboBox's selectedIndexChanged event from firing when the form loads

I have a form with a ComboBox that provides a dropdownlist. On the comboBox's SelectedIndexChanged event, am running some code, but I don't want that code to run when the form loads. Unfortunately, when I load the form (before I make a selection in the combobox), SelectedIndexChanged of the combobox fires (I think when the combobox is databinding). Is there a way of avoiding such behaviour?
If you want to react only when the user change the selected item in the combo box, then it is better to subscribe to SelectionChangeCommitted.
You can simply unbind the SelectedIndexChanged event, call your fill function and bind the SelectedIndexChanged event again. Unfortunately, this doesn't work with a grid.
For example:
this.cmb.SelectionChanged -= new System.EventHandler(this.cmb_SelectionChanged);
cmb.fill(); //Your function
this.cmb.SelectionChanged += new System.EventHandler(this.cmb_SelectionChanged);
Be sure to set the DataSource property in your onload() function after assigning the ValueMember and Datamember properties.
This will help you to solve your problem!
Why not have a boolean flag that indicates when your Form has finished loading?
In your SelectionChanged event, check if the boolean flag is true. If it is true then handle the event, otherwise ignore it.
VB
RemoveHandler lbxNomes.SelectedIndexChanged, AddressOf lbxNomes_SelectedIndexChanged
lbxNomes.DataSource = dst
Label1.Text = String.Format("Encontrados {0} Sócios nesta pesquisa", dst.Rows.Count)
Label1.Visible = True
AddHandler lbxNomes.SelectedIndexChanged, AddressOf lbxNomes_SelectedIndexChanged
Here is a simple solution that leaves your code almost untouched:
In the SelectedIndexChanged event, check if the myComboBox handle is created using the (IsHandleCreated) method. Another added check is to check if the user is actually focusing your combobox control to change selected index.
private void myComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (myComboBox.IsHandleCreated && myComboBox.Focused)
{
// Do something here
}
}
It worked for me in a way with the following code:
private void ddlChapter_SelectionChangeCommitted(object sender, EventArgs e)
{
if (ddlChapter.SelectedValue != null)
{
// Do something here
}
}

this.dragmove() interfering with mouseup event wpf

I have a UserControl in WPF.
The UserControl has a MouseLeftMouseButtonUp event.
The problem is- the Window has a this.DragMove() method in its MouseDown event which seems to interfere with the MouseLeftMouseButtonUp in the User Control (I need the this.DragMove() method to move the borderless window).
Any ideas?
Thanks!
DragMove is a synchronous call; it blocks until the user is done moving the window. This means once DragMove returns, the left button is up. Add your code immediately after your DragMove() call and you should be fine.
I ran into the same problem but found the answer. Your Window_MouseDown event will not run if the MouseDown has already been handled, so all you have to do to prevent DragMove from interfering with your control's mouse events is add this code:
Private Sub YourControl_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Input.MouseButtonEventArgs) Handles YourControl.MouseDown
e.Handled = True
End Sub
private void MouseDown(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
if (e.LeftButton == MouseButtonState.Pressed)
{
this.DragMove();
}
if (e.LeftButton == MouseButtonState.Released)
{
//your mouse up code
}
}
I had issues like this too and found that using click events instead of mousebutton events kept from firing dragmove. For my fix I just had to swap a label for a button. It's possible you could subclass a different element for your usercontrol so that you could pick up a click event to use?

Handling events from user control containing a WPF textbox

In order to take advantage of the spell checking ability of WPF textboxes, I have added one to a user control (with the use of elementhost). This user control is used in various window forms. My current problem is trying to handle keyup events from this textbox but the windows form is unable to "get" any event from the control. I can access the properties of the textbox just fine (i.e. text, length, etc.) but keyboard events don't seem to work.
I have found, however, that the following will bring back events from the WPF textbox:
Public Class MyUserControl
Private _elementHost As New ElementHost
Private _wpfTextbox As New System.Windows.Controls.Textbox
Private Sub MyUserControl_Load(...) Handles Me.Load
Me.Controls.Add(_elementHost)
_elementHost.Dock = DockStyle.Fill
_elementHost.Child = _wpfTextbox
Dim MyEventInfo As EventInfo
Dim MyMethodInfo As MethodInfo
MyMethodInfo = Me.GetType().GetMethod("WPFTextbox_KeyUp")
MyEventInfo = _wpfTextBox.GetType().GetEvent("PreviewKeyUp")
Dim dlg As [Delegate] = [Delegate].CreateDelegate(MyEventInfo.EventHandlerType, Me, MyMethodInfo)
MyEventInfo.AddEventHandler(_wpfTextBox, dlg)
End Sub
Public Sub WPFTextbox_KeyUp(ByVal sender As Object, ByVal e As RoutedEventArgs)
' something goes here
End Sub
End Class
The user control is now able to do something after the PreviewKeyUp event is fired in the WPF textbox. Now, I'm not completely sure how to have the window form containing this user control to work with this.
Im a C# person not VB so please bear with me.. Basically you could assign the event from your Window rather than within your UserControl.. So in the constructor of your Window assign the PreviewKeyUp:
this.myUserContorl.PreviewKeyUp += new System.Windows.Input.KeyEventHandler(WPFTextbox_KeyUp);
then place the event handler in your Window:
private void WPFTextbox_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
}
Incidentally you needn't go through the hassle of capturing the event in your UserControl as you can still access your TextBox within you UserControl directly from your Window (if you make it public), again from your constructor in your Window:
this.myUserContorl.wpfTextbox.PreviewKeyUp += new System.Windows.Input.KeyEventHandler(WPFTextbox_KeyUp);
I imagine it would look like this in VB (at a guess):
AddHandler myUserContorl.wpfTextbox.PreviewKeyUp, AddressOf WPFTextbox_KeyUp
ElementHost has a static method called EnableModelessKeyboardInterop(). Try calling it?
ElementHost.EnableModelessKeyboardInterop();
Read more here
Seems basic, but did you set the KeyPreview to TRUE on your form?

Equivalent to a keypreview property in WPF

I'm pondering taking the plunge to WPF from WinForms for some of my apps, currently I'm working on the combined barcode-reader/text-entry program (healthcare patient forms).
To be able to process the barcode characters, I rely on the Keypreview property in WinForms (because barcodes can be scanned regardless of what control has the focus).
But I cannot seem to find a KeyPreview property in neither VS2008 or VS2010, for a WPF app.
Is there an alternative approach/solution to handle my barcode characters in WPF?
Rgrds Henry
use the override in your own UserControls or Controls (this is an override from UIElement)
protected override void OnPreviewKeyDown(System.Windows.Input.KeyEventArgs e) {
base.OnPreviewKeyDown(e);
}
if you want to preview the key down on any element which you dont create you can do this:
Label label = new Label();
label.PreviewKeyDown += new KeyEventHandler(label_PreviewKeyDown);
and then have a handler like so :-
void label_PreviewKeyDown(object sender, KeyEventArgs e) {
}
if you mark the event as handled (e.Handled = true;) this will stop the KeyDown event being raised.
Thanks got it working! Only problem was I'm coding in VB not C#, but the basic idea holds. Neat to create a label out of thin air and use it to insert yourself in the event stream.
If someone else is interested of the same solution but in VB for WPF, here's my test program, it manages to toss all 'a' characters typed, no matter what control has the focus:
Class MainWindow
Dim WithEvents labelFromThinAir As Label
Private Sub Window_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
AddHandler MainWindow.PreviewKeyDown, AddressOf labelFromThinAir_PreviewKeyDown
End Sub
Private Sub labelFromThinAir_PreviewKeyDown(ByVal sender As Object, ByVal e As KeyEventArgs)
TextBox1.Text = e.Key ' watch 'em coming
If (44 = e.Key) Then e.Handled = True
End Sub
End Class
P.S. This was my first post on stackoverflow, really a useful site. Perhaps I'll be able to answer some questions in here myself later on :-)
WPF uses event bubbling and tunneling. In other words the events travel down and up the visual element tree. Some events will have a corresponding Preview event. So MouseDown will have a PreviewMouseDown that you can respond to. Check out this link and scroll down to the WPF Input Events section.

Resources