Установите для ComboBox SelectedItem объект данных, отсутствующий в ItemSource - PullRequest
1 голос
/ 21 марта 2011

У меня есть поле со списком, свойства SelectedItem и ItemSource которого привязаны к модели представления. Объекты в ItemSource чувствительны ко времени, так как срок их действия истекает, и я могу установить только активные элементы в коллекции на ItemSource. Теперь в определенный момент объект selectedItem может отсутствовать в ItemSource. Я думаю, что нормальное поведение ItemSource - разрешать выбор объектов только из коллекции ItemSource, но в этом случае я хочу выбрать объект, которого больше нет в ItemSource. Как я могу реализовать это поведение? Я опубликую некоторый код здесь, чтобы поддержать мою проблему.

Window.xaml

 <Window x:Class="ExpiredSelectedItem.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 Height="23" 
              HorizontalAlignment="Left" 
              Margin="184,68,0,0" 
              Name="comboBox1" 
              VerticalAlignment="Top" 
              Width="120" 
              ItemsSource="{Binding CustomList}"
              SelectedItem="{Binding ActiveItem}"
              SelectedValue="Code"
              SelectedValuePath="{Binding ActiveItem.Code}"
              DisplayMemberPath="Code"
              />
</Grid>

Window.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ExpiredSelectedItem
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>

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

        CustomList = new List<DomainObject>();

        CustomList.AddRange(new DomainObject[] {
            new DomainObject() { Code = "A", IsActive =true},
            new DomainObject() { Code ="B", IsActive = true},
            new DomainObject() { Code = "C", IsActive =true},
        });

        ActiveItem = new DomainObject() { Code = "D", IsActive = false };

        this.DataContext = this;
    }


    public List<DomainObject> CustomList { get; set; }

    public DomainObject ActiveItem { get; set; }
}

public class DomainObject
{
    public string Code { get; set; }
    public bool IsActive { get; set; }

}

}

Несмотря на то, что я выбираю код D в коде позади, когда в комбинированном списке загружается первый элемент (A), выбран. Ожидаемое поведение состояло в том, что «D» должен был быть выбран в текстовом поле, но никаких элементов не должно быть при открытии раскрывающегося списка.

Ответы [ 2 ]

0 голосов
/ 26 марта 2011

Чтобы сохранить выбранный элемент, когда его нет в списке, вы можете сделать следующее:

  • Запретить установке ActiveItem значение NULL; смотрите: if (значение! = ноль)
  • Очистить ComboBox; см .: comboBox1.SelectedIndex = -1;
  • Реализация INotifyPropertyChanged (что вы, вероятно, уже делаете)

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

Вот код:

using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;

namespace ComboBoxSelectedItem
{
  public partial class MainWindow : Window, INotifyPropertyChanged
  {
    public event PropertyChangedEventHandler PropertyChanged;
    void Notify(string propName)
    {
      if (PropertyChanged != null)
      {
        PropertyChanged(this, new PropertyChangedEventArgs(propName));
      }
    }

    public MainWindow()
    {
      InitializeComponent();

      CustomList = new List<DomainObject>();

      CustomList.AddRange(new DomainObject[] {
        new DomainObject() { Code = "A", IsActive =true},
        new DomainObject() { Code ="B", IsActive = true},
        new DomainObject() { Code = "C", IsActive =true},
        });

      this.DataContext = this;
    }

    public List<DomainObject> CustomList { get; set; }

    private DomainObject _activeItem = new DomainObject() { Code = "D", IsActive = false };
    public DomainObject ActiveItem 
    {
      get { return _activeItem; }
      set
      {
        if (value != null)
        {
          _activeItem = value;
        }

        Notify("ActiveItem");
      }
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
      ActiveItem = new DomainObject() { Code = "D", IsActive = false };
      comboBox1.SelectedIndex = -1;
    }
  }
}

Вот XAML:

<Window x:Class="ComboBoxSelectedItem.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>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <ComboBox 
        Grid.Row="0"
        Height="23" 
        HorizontalAlignment="Left" 
        Name="comboBox1" 
        VerticalAlignment="Top" 
        Width="120" 
        ItemsSource="{Binding CustomList}"
        SelectedItem="{Binding ActiveItem}"
        DisplayMemberPath="Code"/>
    <TextBox 
        Grid.Row="1"
        Text="{Binding Path=ActiveItem.Code, Mode=TwoWay}"/>
    <Button 
        Grid.Row="2" 
        Content="D" 
        Click="Button_Click"/>
  </Grid>
</Window>
0 голосов
/ 21 марта 2011

Я не знаю, играет ли это какую-либо роль, но это выглядит подозрительно. Попробуйте удалить его:

<ComboBox ... SelectedValue="Code" ...
...