WPF DisplayMemberPath does not update when SelectedItem is uninstalled

I have simplified this problem as much as I can. I basically redefine the "null" value of combobox. Thus, if the selected item is deleted, it returns to "(null)". Unfortunately, the behavior of this is wrong, I delete delete, the ObservableCollection element is deleted, so the property binding is updated and returns the "(null)" element as expected. But the appearance of the combobox appears blank. However, the value that it is associated with is correct ... this problem can be reproduced using the code below.

To reproduce this problem, you select an item and delete it. Please note that at this moment the next line is called (when deleting the selected item). So this is a good place for a breakpoint.

if (m_Selected == null) { return Items[0]; //items 0 is ItemNull } 

Also note that I fixed the fix by running a property update in DisplayMemberPath. This did not work.

MainWindow.xaml

 <Window x:Class="WPFCodeDump.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <StackPanel> <ComboBox ItemsSource="{Binding Items}" SelectedItem="{Binding Selected, Mode=TwoWay}" DisplayMemberPath="Name"></ComboBox> <Button Click="ButtonBase_OnClick">Remove Selected</Button> </StackPanel> </Window> 

MainWindowViewModel.cs

 using System.Collections.ObjectModel; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Windows.Input; namespace WPFCodeDump { public abstract class ViewModelBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "") { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } } //Item class public class Item : ViewModelBase { public Item(string name) { m_Name = name; } public string Name { get { return m_Name; } } private string m_Name; public void ForcePropertyUpdate() { OnPropertyChanged("Name"); } } //Item class public class ItemNull : Item { public ItemNull() : base("(null)") { } } class MainWindowViewModel : ViewModelBase { public MainWindowViewModel() { m_Items.Add(new ItemNull()); for (int i = 0; i < 10; i++) { m_Items.Add(new Item("TestItem" + i)); } Selected = null; } //Remove selected command public void RemoveSelected() { Items.Remove(Selected); } //The item list private ObservableCollection<Item> m_Items = new ObservableCollection<Item>(); public ObservableCollection<Item> Items { get { return m_Items; } } //Selected item private Item m_Selected; public Item Selected { get { if (m_Selected == null) { return Items[0]; //items 0 is ItemNull } return m_Selected; } set { m_Selected = value; OnPropertyChanged(); if(m_Selected!=null) m_Selected.ForcePropertyUpdate(); } } } } 

MainWindow.xaml.cs

 using System.Windows; namespace WPFCodeDump { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); DataContext = new MainWindowViewModel(); } private void ButtonBase_OnClick(object sender, RoutedEventArgs e) { ((MainWindowViewModel) DataContext).RemoveSelected(); } } } 

Result:

Result after pressing remove

+5
source share
1 answer

Good binding problem you found there. But, as always, it is our fault, not theirs :)

The problem is (is) using DisplayMemberPath with SelectedItem . DisplayMemberPath does not give f *** about changing SelectedItem .

What you need to do to solve this problem, there are two things:

First, in the RemoveSelected method, set the Selected property to null (to force the binding to be updated):

 public void RemoveSelected() { Items.Remove(Selected); Selected = null; } 

Then, in the XAML definition, change the associated property:

 <ComboBox ItemsSource="{Binding Items}" SelectedValue="{Binding Selected, Mode=TwoWay}" DisplayMemberPath="Name"/> 

Binding the SelectedValue property will correctly update the displayed text in the ComboBox .

+3
source

Source: https://habr.com/ru/post/1213991/


All Articles