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

时间:2014-03-06 10:09:47

标签: c# wpf combobox

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

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

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

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

在XAML中

<Window x:Class="TestProject1.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">
    <Grid>
        <ComboBox IsSynchronizedWithCurrentItem="False" ItemsSource="{Binding Items}"
                  IsEditable="True" Text="{Binding SelectedText, UpdateSourceTrigger=PropertyChanged}"
                  HorizontalAlignment="Left" Margin="10,39,0,0" VerticalAlignment="Top" Width="120"/>
        <Button Click="Button_Click" Content="Update list" 
                HorizontalAlignment="Left" Margin="10,82,0,0" VerticalAlignment="Top" Width="75"/>
    </Grid>
</Window>

在代码背后:

public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public MainWindow() {
            InitializeComponent();

            this.DataContext = this;
            Items = new List<string>() { "0", "1", "2" };
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged(string propertyName) {
            if (PropertyChanged != null) {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        private List<string> _items;
        public List<string> Items {// I use IEnumerable<string> 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
        }

    }

2 个答案:

答案 0 :(得分:0)

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

因此,在您的Items集合设置器中,进行更改:

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

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

答案 1 :(得分:0)

这是我对该问题的解决方法:

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;
        }
    }
}