如何使用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
,然后在更改完成后替换它。
- 复制
SelectedText
- 修改项目来源
- 将
SelectedText
替换为副本