Запретить ComboBox запускать событие SelectionChanged, когда элементы имеют одинаковое имя? - PullRequest
2 голосов
/ 10 марта 2019

У меня есть 2 ComboBoxes, Числа и Цвета .

Выбор Числа ComboBox изменит Item Source Цвета ComboBox.


Проблема:

Я хочу, чтобы Цвета ComboBox не запустили SelectionChanged событие, если недавно выбранный элемент имеет то же имя, что и предыдущий элемент, например «Красный» в Item Source 1 и «Красный» в Item Source 2.


Числа ComboBox

Это ComboBox изменяет Item Source из Цвета 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;
    }
}

Список элементов источника источника

НеСобытие Fire SelectionChanged

Если я использую List<string> для Item Source, а SelectedItem имеет то же имя, что и предыдущий элемент, он не будет запускать ComboBox SelectionChangedсобытие.

<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"
};

Элемент класса списка Источник (проблема)

Событие выбора пожара

Я хочу использовать этот пользовательский class List<ViewModel.MyColors> для Item Source, поэтому я могу связать несколько значений, но он запускает ComboBox SelectionChanged событие.

<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 Ответ

0 голосов
/ 02 апреля 2019

Это хак, который я использую. Он по-прежнему запускает SelectionChanged Event, но игнорирует код, который обычно запускается при его запуске, потому что я переместил этот код в 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
        }

    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...