5

I have a ComboBox:

<ComboBox Name="drpRoute" SelectionChanged="drpRoute_SelectionChanged" />

And I set the list items in the code behind file:

public ClientReports()
{
    InitializeComponent();
    drpRoute.AddSelect(...listofcomboxitemshere....)
}


public static class ControlHelpers
{
    public static ComboBox AddSelect(this ComboBox comboBox, IList<ComboBoxItem> source)
    {
        source.Insert(0, new ComboBoxItem { Content = " - select - "});

        comboBox.ItemsSource = source;
        comboBox.SelectedIndex = 0;

        return comboBox;
    }
}

For some reason, when I set the SelectedIndex, the SelectionChanged event get's fired.

How on earth do I set the ItemSource and set the SelectedIndex without firing the SelectionChanged event?

I am new to WPF, but surely it should not be as complicated as it seems? or am I missing something here?

stoic
  • 4,700
  • 13
  • 58
  • 88
  • Why you don't want it to fire the `SelectionChanged` event? – 123 456 789 0 Feb 20 '14 at 18:38
  • Not sure I follow your question properly but "Selection Changed" firing when the selection index changes seems logical to me. If you do not want it invoked when index is set to 0, in your `SelectionChanged` handler check the new index and if it's 0 just bail out without doing the rest of your selection changed logic. – Viv Feb 20 '14 at 18:38
  • I get the datasource, I set the dropdown with default "select". After that the user can select an item, and when they select it there I `SelectionChanged` event get's fired iand I dow a whole bunch of things on the page based on the dropdown selection. what happens now is, when I set the original datasource, the logic for selection is executed due to `SelectionChanged` event being fired on load. – stoic Feb 20 '14 at 18:41
  • 1
    or before you set the SelectedIndex to 0, remove the handler and attach it again after setting the SelectedIndex. something like `comboBox.SelectionChanged -= drpRoute_SelectionChanged; comboBox.SelectedIndex = 0; comboBox.SelectionChanged += drpRoute_SelectionChanged;` – Viv Feb 20 '14 at 18:42
  • So you want a watermark to say "Select". Can you just set the `Text` property of the `ComboBox` to "Select" ? – 123 456 789 0 Feb 20 '14 at 18:42
  • @Viv That is ugly just for a simple problem. – 123 456 789 0 Feb 20 '14 at 18:42
  • @lll well tbh, this shouldnt even be a problem as the selection handler should check the new index and if it's the index of the placeholder, then it shouldnt do it's normal business logic on it and bail as I suggested in my previous comment. However removing and assigning the handler is an approach that would still work. Choice basically goes to the person writing the code to make. – Viv Feb 20 '14 at 18:44
  • simply setting the text value in code behind does not add the "select" watermark, unsubscribing from the eventhandler is also not really an option. if you look at my example above, you will notice I have a static extensionmethod that I use on multiple dropdowns, the method is not aware of any event handelers, so i will need to pass some reference everytime – stoic Feb 20 '14 at 18:50

2 Answers2

10

The SelectionChangedevent will fire regardless if it was set through code or by user interaction. To get around this you will need to either remove the handler when you are changing it in code as @Viv suggested or add a flag to ignore the changes while you are changing it in code. The first option will not fire the event since you are not listening to it and in the second, you will need to check the flag to see if it was triggered by a change in code.

Update: Here's an example of using a flag:

bool codeTriggered = false;

// Where ever you set your selectedindex to 0
codeTriggered = true;
comboBox.SelectedIndex = 0;
codeTriggered = false;

// In your SelectionChanged event handler
if (!codeTriggered)
{
   // Do stuff when user initiated the selection changed
}
evanb
  • 3,061
  • 20
  • 32
  • ` add a flag to ignore the changes while you are changing it in code` what i am looking for, but not sure how to accomplish. – stoic Feb 20 '14 at 18:52
4

You can solve this problem with data binding :

private int _sourceIndex;
public int SourceIndex
{
    get { return _sourceIndex; }
    set
    {
        _sourceIndex= value;
        NotifyPropertyChanged("SourceIndex");
    }
}

private List<ComboBoxItem> _sourceList;
public List<ComboBoxItem> SourceList
{
    get { return _sourceList; }
    set
    {
        _sourceList= value;
        NotifyPropertyChanged("SourceList");
    }
}

public ClientReports()
{
    InitializeComponent();

    // Set the DataContext
    DataContext = this;

    // set the sourceIndex to 0
    SourceIndex = 0;

    // SourceList initialization
    source = ... // get your comboboxitem list
    source.Insert(0, new ComboBoxItem { Content = " - select - "});
    SourceList = source
}

In the XAML bind SelectedItem and ItemsSource

<ComboBox Name="drpRoute" 
   ItemsSource="{Binding SourceList}"
   SelectedIndex="{Binding SourceIndex}" />

With databinding, everytime you change SourceIndex in your code it changes in the UI, and if you change it in the UI it changes in the class too, you can try to find tutorials about the MVVM design pattern it's a great way to write WPF application.

Aurelien Souchet
  • 721
  • 5
  • 11
  • This is the correct approach to the problem, as it is impossible to remove the SelectionChanged event as the other answer notes. – BradleyDotNET Feb 20 '14 at 18:52
  • MVVM is not implemented in this project, it is a small one pager application :( – stoic Feb 20 '14 at 18:54
  • the example i wrote is not really MVVM (mvvm would have a ModelView as the datacontext) but just some simple databinding, you can use that to solve this particular problem and use events when it's work fine. – Aurelien Souchet Feb 20 '14 at 19:00
  • 1
    @LordTakkera I do not suggest to remove the `SelectionChanged` event but the event handler. You can, in fact, remove the event handler. – evanb Feb 20 '14 at 20:15
  • @evanb I totally agree. Thank you for clarifying – BradleyDotNET Feb 20 '14 at 20:38
  • "and if you change it in the UI it changes in the class too": Nop If you don't use Mode=TwoWay in the binding... – Cabuxa.Mapache Jan 12 '17 at 11:23