Подтвердить что ты не робот

Редактируемый ComboBox WPF

У меня есть свойство ComboBox и ComboBox.IsEditable установлено значение True, чтобы ComboBox действовал как TextBox, так и выпадающий список одновременно. Но когда ComboBox привязан к данным, ввод пользовательского текста не приведет к добавлению нового элемента в связанную с данными коллекцию.

Например, если я введу "Joe" в ComboBox, который привязан к списку людей, который не содержит значения "Joe" , тогда значение "Joe" не будет добавлено к капле - список вниз автоматически.

Каков наилучший способ справиться с этим?

4b9b3361

Ответ 1

Вот базовый MVVM способ получения желаемого поведения:

MainWindow.xaml

<Window x:Class="WpfApplication1.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 Margin="30,5,30,5"
                  IsEditable="True"
                  ItemsSource="{Binding Items}"
                  SelectedItem="{Binding SelectedItem}"
                  Text="{Binding NewItem, UpdateSourceTrigger=LostFocus}"/>
        <TextBox Margin="30,5,30,5" />
    </StackPanel>
</Window>

MainWindow.cs

public partial class MainWindow : Window, INotifyPropertyChanged
{
    private string _selectedItem;

    private ObservableCollection<string> _items = new ObservableCollection<string>()
    {
        "One",
        "Two",
        "Three",
        "Four",
        "Five",
    };

    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
    }

    public IEnumerable Items
    {
        get { return _items; }
    }

    public string SelectedItem
    {
        get { return _selectedItem; }
        set
        {
            _selectedItem = value;
            OnPropertyChanged("SelectedItem");
        }
    }

    public string NewItem
    {
        set
        {
            if (SelectedItem != null)
            {
                return;
            }
            if (!string.IsNullOrEmpty(value))
            {
                _items.Add(value);
                SelectedItem = value;
            }
        }
    }

    protected void OnPropertyChanged(string propertyName)
    {
        var handler = this.PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

Мне пришлось поместить другой элемент управления в окно, поскольку я установил свойство UpdateSourceTrigger привязки Text к LostFocus. Если в окне нет других элементов управления, тогда Combobox никогда не потеряет фокус.

Я изменил режим обновления, потому что режим обновления по умолчанию Propertychanged, который добавит новый элемент для каждого нажатия клавиши.

например. если вы введете текст "Окно", в вашу коллекцию будет добавлено следующее:

W
Wi
Win
Wind
Windo
Window

Ответ 2

Я бы справился с этим в событии LostFocus.

Здесь вы можете проверить, имеет ли значение SelectedItem значение null. Если это так, добавьте значение Text в список ограничений и установите SelectedItem в новый элемент.

В XAML:

  <ComboBox Name="_list" LostFocus="LostFocus" IsEditable="True"/>

В кодировке:

    private ObservableCollection<string> _names;
    public MainWindow()
    {
        InitializeComponent();
        _names = new ObservableCollection<string> {"Eric", "Phillip"};
        _list.SetBinding(ItemsControl.ItemsSourceProperty, new Binding {Source = _names});
    }

    private void LostFocus(object sender, RoutedEventArgs e)
    {
        var comboBox = (ComboBox) sender;
        if(comboBox.SelectedItem != null)
            return;
        var newItem = comboBox.Text;
        _names.Add(newItem);
        comboBox.SelectedItem = newItem;
    }

Надеюсь, что это поможет:)

Ответ 3

Мое предложение будет использовать MVVM-подход и привязать ваш ComboBox.Text к некоторому TextProperty вашего ViewModel. (То же самое можно достичь, просто добавив свойство строки к вашему представлению) Затем вы можете обработать ввод в установщике этого свойства и добавить этот новый элемент в список, независимо от того, каким образом он был "зафиксирован" в представлении. AFAIK не существует готового механизма для добавления новых элементов в ваш источник данных, вам все равно придется самому генерировать элементы.

В качестве альтернативы вы можете связать оба - SelectedItem и Text вашего ComboBox - чтобы избежать поиска, если пользователь ввел известный элемент. Но эта часть может быть менее важной для ответа на ваш вопрос.