WPF Combobox SelectionChanged event - wpf

I have a project where I have a ComboBox interacting with 2 Sliders.
Each o these 3 controls are triggered by events: namely a SelectionChanged for the ComboBox and a ValueChanged for the 2 sliders.
I thought the ValueChanged event was giving me problems, not updating the values and min/max accordingly to the combobox selection. For some reason I assumed that maybe both events were triggered simultaneously resulting in a mix up of my variables.
Well, I decided to change my ValueChanged events so that they only update a label so see if that fixed the problem. It did not.
In other words, the SelectionChanged event is where my problem is lying.
Looking through my code I didn't see any problem, and at this point the only thing I can think of is as follow:
private void chanList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
switch (chanList.Text)
{
case "Channel 1":
{ // blablabla }
}
}
Reason for the problem is that chanList.Text doesn't contain the "new selection", it still contains the old one. I am guessing that when the "SelectionChanged" event is triggered, the content of the of combobox (in my case chanList.Text) is not yet "updated". So it results in picking up the wrong case in my switch.
Now my questions:
1. are my assumptions correct?
2. if so, what should I replace my Switch test by? Assuming chanList.Text isn't updated yet, maybe going with something chanList.SelectedItem should be the way to go. However, I was able to find the correct verbose to access the content (text) of the selected item... That's why I was going with chanList.Text which has been working fine well at least until I started using that event.
Thanks for the help!
Steve

The combobox text will not be changed in the SelectionChanged event handler. The selections will be found in the SelectionChangedEventArgs object. Specifically e.AddedItems. It is possible, although perhaps not for your control, that the user will have selected multiple items in the combobox, so e.AddedItems is a list. Scroll through the list and make the updates necessary.
private void chanList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
foreach (object item in e.AddedItems)
{
if (item is string)
{
switch (item as string)
{
case "Channel 1":
Console.WriteLine("Channel 1");
break;
default:
break;
}
}
}
}

Related

WPF if statement based on radio button checked or not

I'm having difficulty with something which seems like it should be very simple. I'm coming from Windows Forms and starting up with WPF. I think I have a simple syntax issue but I can't seem to find a specific example for this radio button issue.
I have a radio button on my GUI for a query to run either via a map selection or a list. When load is clicked, it should perform one operation if map is selected, a different operation for list. Code looks similar to this:
private void Load_Click(object sender, RoutedEventArgs e)
{
if (rdBtnList.Checked == true)
{
//do this
}
// if rdBtnList not checked (ie if rdBtnMap is checked)
// do this
}
Any help would be greatly appreciated. Thanks.
Change:
if (rdBtnList.Checked == true)
to
if (rdBtnList.IsChecked == true)
Note:
I'm coming from Windows Forms and starting up with WPF
You must forget everything you ever learned in winforms, and embrace MVVM. You should create a ViewModel and bind your rdBtnList.IsChecked property to some boolean value in the ViewModel, then perform your logic in there. The views' code behind is not the right place for application logic.
The property in WPF is called IsChecked hence you just need to update the if statement
if (rdBtnList.IsChecked == true) {
...
}
The IsChecked property is bool? (nullable value) in WPF so you may choose to be more explicit here by doing the following
if (rdBtnList.IsChecked.HasValue && rdBtnList.IsChecked.Value) {
...
}
Are you missing a return statement? As is, the posted code will always execute the if not checked path:
private void Load_Click(object sender, RoutedEventArgs e)
{
if (rdBtnList.IsChecked == true)
{
//do this
return; // return, or the if not checked path below will always win.
}
// if rdBtnList not checked (ie if rdBtnMap is checked)
// do this
}
In WPF, you'll need to use the IsChecked property. See the RadioButton Class for more details.

Silverlight DataGrid MouseLeftButtonDown event not raised when clicking on rows

Note: I have found a solution to my problem so I am posting this for reference purposes, although I would be happy to be educated with a better solution.
I'm trying to provide double click functionality on a Silverlight DataGrid by hooking into the UIElement.MouseLeftButtonDown but when I subscribe to the DataGrid.MouseLeftButtonDown using XAML or the DataGrid.MouseLeftButtonDown += syntax, my event handler is not called when I click on the rows within the DataGrid. If I click on the Header, the event is raised.
If I subscribe to the same event at the parent UserControl level, the event handler is called successfully as you would expect based on Silverlight RoutedEvents but then I have to detect whether the click occurred on the DataGrid or somewhere else.
If I subscribe to the event using this UIElement.AddHandler syntax, as shown below, then it works as expected based on the handledEventsToo: true parameter.
dataGrid.AddHandler(UIElement.MouseLeftButtonDownEvent,
new MouseButtonEventHandler(dataGrid_MouseLeftButtonDown)
, handledEventsToo: true);
It seems that the DataGrid implementation is marking these events as handled, prevent event bubbling, by default in one of the child UIElements, which is not what I expected initially. With more thought I can see that the click behaviour drives all sorts of things (select item, edit field etc.) so perhaps the implementation makes sense.
I had the same problem and I used MouseLeftButtonUp which fires the event but the clickcount value is always 1.
Here is the fix for that:
private const int MOUSE_SENSITIVITY = 300;
private DateTime _previousClick;
private void exceptionsDataGrid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
DataGrid dg = (sender as DataGrid);
DateTime current=DateTime.Now;
LoggerService.Exception exception = (LoggerService.Exception)dg.SelectedItem;
if (_previousClick != null)
{
TimeSpan clickSpan = current - _previousClick;
if (clickSpan.TotalMilliseconds < MOUSE_SENSITIVITY)
{
MessageBox.Show("You double clicked!");
}
}
_previousClick = current;
}

Strange problem with the left-click on a Silverlight DataGrid

I am experiencing some very strange mouse-event behaviour when working with Silverlights DataGrid:
What I want to do is simply call some method when the user left-clicks over my DataGrid. That shouldn't be much a problem, but ...
With
public void doLeftClick (object sender, MouseButtonEventArgs e) {
// some code
}
i am defining the EventHandler and with
myDataGrid.MouseLeftButtonDown += doLeftClick;
i am attaching it to the event.
The result of that is that the doLeftClick method only gets called when i left-click over one of the columns of my DataGrid!
When i am doing the exact same code as above only for the right-click instead of the left-click the EventHandler gets called everytime i right-click over my DataGrid regardless where the mouse cursor is, as long it is inside the boundaries of the control (which is what i actually need with the left-click and what's the behavior i would expect from this setting):
public void doRightClick (object sender, MouseButtonEventArgs e) {
// some code
}
myDatagrid.MouseRightButtonDown += doRightClick;
So what am i doing wrong ? What am i forgetting ?
I really would appreciate any help :)
Marc
The click events are not bubbled up. If a child control marks the event as handled it stops.
In this instance the left click is being eaten by the DataGrid cells (in order to select them and/or give focus to edit controls).
Right click is not used by the cells in the same way, so propagates up to the DataGrid control.
The column headers are nice enough to allow the left click to propagate.

Select ListBox item only on Click or Enter key in Silverlight

When I populate a ListBox with RIA Services, an item is automatically selected. This triggers the SelectionChanged event. If I move the selection up or down with the arrow keys, the event also gets triggered.
I don't want this. I want the user to press enter or click the item for it to be selected. How do I accomplish this?
You could handle the MouseLeftButtonDown and KeyDown events for the ListBox. For the KeyDown event, you'll need to check the EventArgs to determine whether the Enter key was pressed (as opposed to any other key).
These events can fire even when an item is not selected (e.g., if the user clicks inside the ListBox but not over an actual item), so within your event handlers you should check for this.
Your event handlers might look something like this:
public void MyListBox_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
ItemSelected();
}
public void MyListBox_KeyDown(object sender, KeyEventArgs e)
{
if ((e.Key & Key.Enter) == Key.Enter)
{
ItemSelected();
}
}
public void ItemSelected()
{
if (MyListBox.SelectedItem != null)
{
// Handle item selection here
}
}
These are off the top of my head, so you may need to tweak these slightly to get them to work exactly right. Hopefully you see the general idea though.
Another way to do it would be to simply remove the SelectionChanged event handler when populating the ListBox with items (use the "-=" syntax), then re-attach it once this operation is complete.
I'd recommend doing it this way (since you're concerned about the event firing when the list is populated). It wouldn't stop the users from selecting items using the Up and Down arrow keys, but unless you have a really good reason for doing so you're making things unnecessary inconvenient (users don't want to be arbitrarily restricted from doing things that ought to work).

Is there a way to cancel TabControl.Items.CurrentChanging?

There is unfortunately no TabControl.SelectionChanging event (Selector.SelectionChanging), I am struggling to implement this behavior so I can cancel the changing request.
I tried to handle the TabControl.Items.CurrentChanging (the Items property is and ItemCollection) event setting e.Cancel (of the CurrentChangingEventArgs) to true, but the UI is is updated with the new tab although the item is not changed in the collection.
Is there any way to prevent user from switching to a different TabItem when a condition is dissatisfied?
I don't know the exact reason why this happens, and it annoys me greatly.
But here's my workaround for it:
In the sample below, checkbox is "locking" the current tab. So checked means user can't change tab.
void Items_CurrentChanging(object sender, CurrentChangingEventArgs e)
{
if (checkBox1.IsChecked.Value)
{
var item = ((ICollectionView)sender).CurrentItem;
e.Cancel = true;
tabControl1.SelectedItem = item;
}
}
Basically, what happens is (if I understand this correctly) the visual tree gets updated, but the logical tree does not. The above way forces the visual to sync with the logical tree.
You can also handle the PreviewLostKeyboardFocus event on each TabItem, and set the Handled property of the event arguments to true to prevent switching to another tab:
protected void tabItem_PreviewLostKeyboardFocus(object sender,
KeyboardFocusChangedEventArgs e)
{
if (!ValidateTabItem((TabItem) sender)) {
e.Handled = true;
}
}
See http://www.netframeworkdev.com/windows-presentation-foundation-wpf/how-to-cancel-navigation-between-tabitems-in-a-tabcontrol-84994.shtml.

Resources