У меня есть следующий XAML разметку:WPF ComboBox привязки поведение
<TextBox x:Name="MyTextBox" Text="{Binding Path=SelectedCustomer.FavouriteProduct.ProductNumber, UpdateSourceTrigger=PropertyChanged}" />
<ComboBox x:Name="MyComboBox" ItemsSource="{Binding Products}" DisplayMemberPath="ProductName"
SelectedValue="{Binding Path=SelectedCustomer.FavouriteProduct.ProductNumber}"
SelectedValuePath="ProductNumber" />
Мой Посмотреть DataContext-х связан с ViewModel, содержащей государственную собственность под названием SelectedCustomer. Объекты Customer содержат свойство FavouriteProduct объектов Product и Product, содержащих общедоступные свойства ProductNumber и ProductName.
Поведение, которое я ищу, - это чтобы SelectedItem из ComboBox обновил текст в TextBox и наоборот. ComboBox для TextBox работает отлично. Выбор любого продукта в ComboBox обновляет TextBox с номером продукта этого продукта. Однако, когда я пытаюсь пойти другим путем, я получаю странное поведение. Он работает только для элементов, которые поступают перед выбранным элементом. Я попытаюсь объяснить:
Рассмотрим следующий список продуктов ([Номер продукта], [Имя продукта]):
- Fanta
- Пепси
- Coca Cola
- Sprite
- Вода
Теперь скажем, что функция Избранного клиента te продукт Coca Cola (должен быть разработчиком). Поэтому, когда окно открывается, TextBox читает 3, а ComboBox читает Coca Cola. Прекрасный. Теперь измените номер продукта в TextBox на 2. ComboBox обновляет его значение для Pepsi. Теперь попробуйте изменить номер продукта в TextBox на что-нибудь большее, чем число для Coca Cola (3). Не очень мило. При выборе 4 (Sprite) или 5 (Water) ComboBox возвращается обратно в Coca Cola. Таким образом, поведение похоже, что все, что находится ниже элемента, которое вы открываете ширину окна из списка в ItemSource, не работает. Установите его в 1 (Fanta), и никто из других не работает. Установите его на 5 (Вода), и все они работают. Может ли это иметь отношение к некоторой инициализации для ComboBox? Потенциальная ошибка? Любопытно, если кто-либо еще видел это поведение.
UPDATE:
После прочтения ответа Майка Брауна я создал свойство для SelectedProduct и SelectedProductNumber. Проблема, с которой я сталкиваюсь, заключается в том, что как только вы выберете что-то из ComboBox, вы окажетесь в бесконечном цикле, в котором свойства сохраняют updatign друг друга. Я неправильно выполнил обработчик OnPropertyChanged или есть что-то, чего я не вижу? Вот фрагмент кода из моего ViewModel:
private int _SelectedProductNumber = -1;
public int SelectedProductNumber
{
get
{
if (_SelectedProductNumber == -1 && SelectedCustomer.Product != null)
_SelectedProductNumber = SelectedCustomer.Product.ProductNumber;
return _SelectedProductNumber;
}
set
{
_SelectedProductNumber = value;
OnPropertyChanged("SelectedProductNumber");
_SelectedProduct = ProductList.FirstOrDefault(s => s.ProductNumber == value);
}
}
private Product _SelectedProduct;
public Product SelectedProduct
{
get
{
if (_SelectedProduct == null)
_SelectedProduct = SelectedCustomer.Product;
return _SelectedProduct;
}
set
{
_SelectedProduct = value;
OnPropertyChanged("SelectedProduct");
_SelectedProductNumber = value.ProductNumber;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string property)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
UPDATE 2
Я изменил реализацию немного в настоящее время путем обновления SelectedCustomer.FavouriteProduct от обоих свойств, а затем, используя, что при чтении их значения. Теперь это работает, но я не уверен, что это «правильный путь».
private int _SelectedProductNumber = 0;
public int SelectedProductNumber
{
get
{
if (SelectedCustomer.Product != null)
_SelectedProductNumber = SelectedCustomer.Product.ProductNumber;
return _SelectedProductNumber;
}
set
{
_SelectedProductNumber = value;
SelectedCustomer.FavouriteProduct = ProductList.FirstOrDefault(s => s.ProductNumber == value);
OnPropertyChanged("SelectedProductNumber");
OnPropertyChanged("SelectedProduct");
}
}
private Product _SelectedProduct;
public Product SelectedProduct
{
get
{
if (SelectedCustomer.Product != null)
_SelectedProduct = SelectedCustomer.Product;
return _SelectedProduct;
}
set
{
_SelectedProduct = value;
SelectedCustomer.FavouriteProduct = value;
OnPropertyChanged("SelectedProduct");
OnPropertyChanged("SelectedProductNumber");
}
}
Ошибка была на мне ... Я обновил свой ответ с помощью правильного кода. –
Чтобы гарантировать, что вы не активируете измененные события, когда свойство фактически не изменилось, используйте блок 'if (_selectedProduct! = Value) {/*...*/}'. –
Ваше новое решение совершенно справедливо (на самом деле оно позволяет избежать повторяющейся информации, которая отлично). Что странно для меня, однако, вы все еще получаете переполнение стека. Я поместил код в VS, и он отлично работает для меня. Не уверен, что происходит с вашей стороны. Является ли ваше изменение на selectedcustomer.favoriteproduct, также предлагая обновление для двух других свойств? В любом случае, я обновил свой пример кода с версией, которая работает на моей машине (TM) –