如何使用ComboBox的Text属性禁用ItemsSource同步

我使用ComboBox绑定到视图模型的字符串属性。 我选择ComboBox而不是TextBox,因为我想有一个选项从列表中选择(作为建议),但如果ItemsSource更改,我不想更改所选文本。

我尝试将IsSynchronizedWithCurrentItem属性设置为false,但是当建议列表更改时(在所选文本的位置),Text将变为空。 似乎ComboBox记得输入的文本也在列表中,当此项消失时,Text属性也被清除。

所以我的问题是:这是一个错误,还是我做错了什么? 如果它是一个bug,你能建议一些解决方法吗?

我创建了一个示例项目,它预生成了这个:

在XAML中:

   

代码背后:

 public partial class MainWindow : Window, INotifyPropertyChanged { public MainWindow() { InitializeComponent(); this.DataContext = this; Items = new List() { "0", "1", "2" }; } public event PropertyChangedEventHandler PropertyChanged; private void RaisePropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } private List _items; public List Items {// I use IEnumerable with LINQ, but the effect is the same get { return _items; } set { if (_items != value) { _items = value; RaisePropertyChanged("Items"); } } } private string _selectedText; public string SelectedText { get { return _selectedText; } set { if (_selectedText != value) { _selectedText = value; RaisePropertyChanged("SelectedText"); } } } private void Button_Click(object sender, RoutedEventArgs e) { var changed = Items.ToList();//clone int index = changed.IndexOf(SelectedText); if (index >= 0) { changed[index] += "a";//just change the currently selected value } Items = changed;//update with new list } } 

ItemsSource更改后,在所选文本上引发更改的属性以刷新UI。

所以在Items集合setter中,进行更改:

 RaisePropertyChanged("Items"); RaisePropertyChanged("SelectedText"); 

编辑:在您的示例中,您不仅要更改ItemSource,还要更改当前所选项目的文本,但对旧文本具有文本绑定。 你期待看到/发生什么? 您是否希望所选项目保持不变,即使其文本发生变化?

这是我对该问题的修复:

 public class ComboBox : System.Windows.Controls.ComboBox { private bool ignore = false; protected override void OnSelectionChanged(SelectionChangedEventArgs e) { if (!ignore) { base.OnSelectionChanged(e); } } protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e) { ignore = true; try { base.OnItemsChanged(e); } finally { ignore = false; } } } 

像这样修改Button_Click (注释行是新的):

 private void Button_Click(object sender, RoutedEventArgs e) { string tempCopy = SelectedText; // Create a copy of the current value var changed = Items.ToList(); int index = changed.IndexOf(SelectedText); if (index >= 0) { changed[index] += "a"; } Items = changed; SelectedText = tempCopy; // Replace the selected text with the copy we made } 

所有这一切都是在Items更改之前复制SelectedText ,然后在更改完成后替换它。

  1. 复制SelectedText
  2. 修改项目来源
  3. SelectedText替换为副本