#wpf #combobox #equals
#wpf #поле со списком #равно
Вопрос:
У меня здесь есть академический вопрос о Combobox
контроле. Итак, у меня есть этот элемент управления и есть ComboboxItem
класс, экземпляры которого являются элементами в combobox. Я переопределил Equals
метод в ComboboxItem
классе и пытаюсь наблюдать, что именно в нем происходит. И я вижу неожиданное (как я думаю) поведение. Посмотрите.
Ошибка с кодом:
[DebuggerDisplay("N = {Name}")]
public class ComboboxItem
{
public Int32 Id { get; set; }
public String Name { get; set; }
// It is not very correctly written but it is not a problem
public override bool Equals(object obj)
{
if (obj == null)
return false;
var cmb = obj as ComboboxItem;
if (cmb == null)
return false;
if (Id.Equals(cmb.Id))
return true;
return false;
}
}
public partial class MainWindow
{
private ComboboxItem _selectedItem;
private List<ComboboxItem> _source;
public ComboboxItem SelectedItem
{
get { return _selectedItem; }
set
{
_selectedItem = value;
}
}
public List<ComboboxItem> Source
{
get { return _source; }
set { _source = value; }
}
public MainWindow()
{
InitializeComponent();
DataContext = this;
_source = new List<ComboboxItem>
{
new ComboboxItem
{
Id = 1,
Name = "Name11"
},
new ComboboxItem
{
Id = 2,
Name = "Name22"
},
new ComboboxItem
{
Id = 3,
Name = "Name33"
},
};
// Name must be different from "Name33" for better observing
_selectedItem = new ComboboxItem {Id = 3, Name = "AlmostName33"};
}
}
XAML:
<ComboBox ItemsSource="{Binding Source}"
DisplayMemberPath="Name"
SelectedItem="{Binding SelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</ComboBox>
Довольно просто, как вы можете видеть. Это действительно работает, т.Е. Элемент с Name
= «AlmostName33» будет установлен как SelectedItem
in Combobox
.
Проблема заключается в Equals
методе и количестве его вызовов. Я думал Equals
, что будет вызываться только 3 (три!) Раза для сравнения SelectedItem
с каждым элементом Combobox
. Но он вызывает 6 (шесть!) Раз, а параметр obj очень неожиданный для меня. Подробнее:
1) this = «Name11» obj = «Name11» ———- что это такое? Почему не «AlmostName33»?
2) this = «Name11» obj = «AlmostName33»
3) this = «Name22» obj = «AlmostName33»
4) this = «Name22» obj = «AlmostName33»
5) this = «Name33» obj = «AlmostName33»
6) this = «Name33» obj = «AlmostName33»
Может ли кто-нибудь четко объяснить мне, почему у меня шесть вызовов и почему obj = «Name11» при первом вызове?
Обновить
_source = new List<ComboboxItem>
{
new ComboboxItem
{
Id = 1,
Name = "Name11"
},
new ComboboxItem
{
Id = 2,
Name = "Name22"
}
};
var item = new ComboboxItem
{
Id = 3,
Name = "Name33"
},
_source.Add(item);
_selectedItem = item;
Комментарии:
1. 1 за интересный вопрос.
Ответ №1:
После тестирования вашего кода я вообще не могу проверить ваши результаты. Мои результаты частично соответствуют ожиданиям и выглядят следующим образом:
1) this = «Name11» obj = «Name11» — это потому, что изначально было выбрано «Name11».
2) this = «Name11» obj = «AlmostName33» — это потому, что выбирается «AlmostName33».
3) this = «Name22» obj = «AlmostName33» — это потому, что выбирается «AlmostName33».
4) this = «Name33» obj = «AlmostName33» — это потому, что выбирается «AlmostName33».
5) this = «Name11» obj = «AlmostName33»
6) this = «Name22» obj = «AlmostName33»
7) this = «Name33» obj = «AlmostName33»
8) this = «Name11» obj = «AlmostName33»
9) this = «Name22» obj = «AlmostName33»
10) this = «Name33» obj = «AlmostName33»
Итак, по сути, первый вызов Equals
метода был вызван тем "Name11"
, что изначально было выбрано значение… вы можете проверить это, установив точку останова в методе, а затем переходя по коду, пока он не выйдет из метода и не вернется к получателю SelectedItem
свойств.
Следующие три вызова являются ожидаемыми вызовами, в которых Фреймворк сравнивает потенциальное выбранное значение с каждым элементом в коллекции. Затем что-то идет не так. Я подозреваю, что это как-то связано либо с тем фактом, что вы неправильно реализовали свой Equals
метод, либо с тем, что вы пытаетесь выбрать элемент, которого нет в коллекции.
Комментарии:
1. Я могу подтвердить, что
Selector
(и его производные, такие какComboBox
) НЕ поддерживает наличие aSelectedItem
, которое не является частьюItems
коллекции. Следует ожидать неожиданного поведения (без каламбура), если это так.2. Вау! У вас есть даже 10 вызовов. Это еще более странно, чем мои результаты. Если говорить о первом вызове, я проверяю, как вы сказали
SelectedItem
ComboboxItem
, и его значение равно"AlmostName33"
, а не"Name11"
. Но я думаю, что это правильно, я сам установил его значение в конструкторе. Поэтому вопрос о первом вызове с obj ="Name"
остается открытым. Кроме того, я меняюCombobox
инициализацию (см. Обновление) иSelectedItem
теперь является частьюItems
коллекции. И снова у меня те же результаты 🙂