2
votes

I have 2 ComboBoxes, Numbers and Colors.

The Numbers ComboBox selection will change the Item Source of the Colors ComboBox.


Problem:

I want to prevent the Colors ComboBox from firing the SelectionChanged event if a newly selected item has the same name as the previous item, such as "Red" in Item Source 1 and "Red" in Item Source 2.


Numbers ComboBox

This ComboBox changes the Item Source of the Colors ComboBox.

<ComboBox x:Name="cboNumbers"
          SelectedItem="{Binding Numbers_SelectedItem}"
          IsSynchronizedWithCurrentItem="True"
          HorizontalAlignment="Left" 
          Margin="190,55,0,0" 
          VerticalAlignment="Top" 
          Width="120" 
          SelectionChanged="cboNumbers_SelectionChanged"/> 
    <System:String>1</System:String>
    <System:String>2</System:String>
</ComboBox>


// Change Item Source with Selection
//
private void cboNumbers_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (vm.Numbers_SelectedItem == "1")
    {
        vm.Colors_Items = colors1;
    }
    else if (vm.Numbers_SelectedItem == "2")
    {
        vm.Colors_Items = colors2;
    }
}

List String Item Source

Does Not Fire SelectionChanged Event

If I use a List<string> for the Item Source, and the SelectedItem has the same name as the previous item, it will not fire the ComboBox SelectionChanged event.

<ComboBox x:Name="cboColors"
          ItemsSource="{Binding Colors_Items}"
          SelectedItem="{Binding Colors_SelectedItem}"
          IsSynchronizedWithCurrentItem="True"
          HorizontalAlignment="Left" 
          Margin="190,55,0,0" 
          VerticalAlignment="Top" 
          Width="120" 
          SelectionChanged="cboColors_SelectionChanged"/>


// Colors Item Source 1
public List<string> colors1 = new List<string>()
{
    "Red",  //<-- same name (doesn't fire event)
    "Green",
    "Blue"
};

// Colors Item Source 2
public List<string> colors2 = new List<string>()
{
    "Red",  //<-- same name (doesn't fire event)
    "Yellow",
    "Purple"
};

List Class Item Source (Problem)

Fires SelectionChanged Event

I want to use this custom class List<ViewModel.MyColors> for the Item Source, so I can bind multiple values, but it fires the ComboBox SelectionChanged event.

<ComboBox x:Name="cboColors"
          ItemsSource="{Binding Colors_Items}"
          SelectedValue="{Binding Colors_SelectedItem}"
          SelectedValuePath="Name"
          IsSynchronizedWithCurrentItem="True"
          HorizontalAlignment="Left" 
          Margin="190,111,0,0" 
          VerticalAlignment="Top" 
          Width="120" 
          SelectionChanged="cboColors_SelectionChanged">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <Grid>
                <TextBlock Text="{Binding Name}"></TextBlock>
            </Grid>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>


// Colors Item Source 1
public List<ViewModel.MyColors> colors1 = new List<ViewModel.MyColors>()
{
    new ViewModel.MyColors() { Name = "Red",       Value = "a"}, //<-- same name (fires event)
    new ViewModel.MyColors() { Name = "Green",     Value = "b"},
    new ViewModel.MyColors() { Name = "PuBlueple", Value = "c"}
};

// Colors Item Source 2
public List<ViewModel.MyColors> colors2 = new List<ViewModel.MyColors>()
{
    new ViewModel.MyColors() { Name = "Red",    Value = "x"},    //<-- same name (fires event)
    new ViewModel.MyColors() { Name = "Yellow", Value = "y"},
    new ViewModel.MyColors() { Name = "Purple", Value = "z"}
};

ViewModel

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged = delegate { };
    private void OnPropertyChanged(string prop)
    {
        PropertyChangedEventHandler handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(prop));
        }
    }

    // Numbers Selected Item
    private string _Numbers_SelectedItem { get; set; }
    public string Numbers_SelectedItem
    {
        get { return _Numbers_SelectedItem; }
        set
        {
            if (_Numbers_SelectedItem == value) { return; }

            _Numbers_SelectedItem = value;
            OnPropertyChanged("Numbers_SelectedItem");
        }
    }

    // Colors Item Source
    public class MyColors
    {
        public string Name { get; set; }
        public string Value { get; set; }
    }
    public List<MyColors> _Colors_Items = new List<MyColors>();
    public List<MyColors> Colors_Items
    {
        get { return _Colors_Items; }
        set
        {
            _Colors_Items = value;
            OnPropertyChanged("Colors_Items");
        }
    }
    // Colors Selected Item
    private string _Colors_SelectedItem { get; set; }
    public string Colors_SelectedItem
    {
        get { return _Colors_SelectedItem; }
        set
        {
            if (_Colors_SelectedItem == value) { return; }

            _Colors_SelectedItem = value;
            OnPropertyChanged("Colors_SelectedItem");
        }
    }
}
1
did u find any solution for this?Avinash Reddy
@Avinash Hi, I have not found a solution yet.Matt McManis
im having almost same issueAvinash Reddy
@Avinash I had to create a hack, but I'd like to find a more professional solution. I will see if I can post the code as an answer if you want to take a look.Matt McManis
@Avinash Sorry, actually that was another part of the code. I was not able to prevent the ComboBox from firing the event. I modified the VieModel bound SelectedItem string so it would ignore some of the code when it fired. Then it was almost the same as having it not fire.Matt McManis

1 Answers

0
votes

This is the hack I'm using. It still fires the SelectionChanged Event, but ignores the code that would normally be run when it fires, because I moved that code to the ViewModel SelectedItem bound String.

ComboBox

public static string colors_PreviousItem;

private void cboColors_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    // Save the Previous Item
    if (!string.IsNullOrEmpty(vm.Colors_SelectedItem))
    {
        colors_PreviousItem = vm.Colors_SelectedItem;
    }

    // Select Item
    vm.Colors_SelectedItem = SelectItem(vm.Colors_Items.Select(c => c.Name).ToList(),
                                        colors_PreviousItem
                                        );

    // I used to have the code I want to run in here
}


// Select Item Method
//
public static string SelectItem(List<string> itemsName,
                                string selectedItem
                                )
{
    // Select Previous Item
    if (itemsName?.Contains(selectedItem) == true)
    {
        return selectedItem;
    }

    // Default to First Item
    else
    {
        return itemsName.FirstOrDefault();
    }
}

ViewModel

// Selected Item
//
private string _Colors_SelectedItem { get; set; }
public string Colors_SelectedItem
{
    get { return _Colors_SelectedItem; }
    set
    {
        var previousItem = _Colors_SelectedItem;
        _Colors_SelectedItem = value;
        OnPropertyChanged("Colors_SelectedItem");

        // Ignore if Previous Item is different than New Item
        if (previousItem != value)
        {
            // Moved the code I want to run in here
            // I want to ignore the code in here when the SelectionChanged Event fires 
            // and the Previous and Newly Selected Items are the same
        }

    }
}