Как IEQuatable <T>влияет на поведение комбобокса - PullRequest
0 голосов
/ 14 марта 2011

Во время работы со списком я обнаружил проблему с проводной связью. Xaml выглядит так

<ComboBox x:Name="cb" ItemsSource="{Binding MyEntity.Choices}" 
              SelectedItem="{Binding MyEntity.Choice,Mode=TwoWay}" 
              Height="25" 
              HorizontalAlignment="Stretch"
              VerticalAlignment="Top"/>

Предположим, что Itemsource связан со списком валов (объект), а selectedItem - один из списка.

public partial class MainWindow : Window
{
    private ShaftsData shaftData;

    public ShaftsData ShaftData
    {
        get { return shaftData; }
        set { shaftData = value; }
    }
    public MainWindow()
    {
        ShaftData = new ShaftsData();
        InitializeComponent();
        txtBox.Text = "Default";
        this.DataContext = this;
        SetComboCollectionAndSelectedShaft();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        shaftData.ComboCollection = null;
    }

    private void SetComboCollectionAndSelectedShaft()
    {
        Collection<Shaft> myCollection = new Collection<Shaft>();
        for (int i = 1; i <= 5; ++i)
        {
            Shaft sh = new Shaft();
            sh.Id = i;
            sh.Name = string.Format("{0} {1} ", txtBox.Text, i);
            myCollection.Add(sh);
        }
        shaftData.ComboCollection = myCollection;
        shaftData.SelectedShaft = shaftData.ComboCollection[0];
    }
}

 public class ShaftsData : INotifyPropertyChanged
{
    private Collection<Shaft> _comboCollection;
    private  Shaft _selectedShaft;

    public Collection<Shaft> ComboCollection
    {
        get
        {
            return _comboCollection;

        }
        set
        {
            _comboCollection = value;
            OnPropertyChanged("ComboCollection");
        }
    }

    public Shaft SelectedShaft
    {
        get { return _selectedShaft; }
        set
        {
            _selectedShaft = value;
            OnPropertyChanged("SelectedShaft");
        }
    }

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

И затем я попытался сделать этот список нулевым (пожалуйста, обратитесь к Button_Click). Combobox вызывает .Equals для каждого объекта списка и сравнивает последний выбранный объект. Хотя я ожидаю, что он не должен вызывать .equals и устанавливать SelectedItem на ноль.

 public class Shaft
{
    private int _id;
    private string _name;

    public int Id {
        get { return _id; }
        set {
            _id = value;
        }
    }

    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
        }
    }

    public override string ToString()
    {
        return _name;
    }

    public override bool Equals(object obj)
    {
        System.Diagnostics.Debug.WriteLine("Calling from object.Equals");
        Shaft shaft = obj as Shaft;
        if (null != shaft)
        {
            System.Diagnostics.Debug.WriteLine("Equals called for " + this.Name + ". Compared with " + shaft.Name);
        }
        else
        {
            System.Diagnostics.Debug.WriteLine("Equals called for " + this + ". Compared with " + shaft);
        }
        return base.Equals(obj);
    }

Теперь, если я реализую IEquatable на Shaft, а затем установлю для List значение null, все будет нормально. Означает, что вызов не выполняется .Eqauls & selectedItem имеет значение null.

Новая реализация

public class Shaft : IEquatable<Shaft>
    {
        private int _id;
        private string _name;

        public int Id {
            get { return _id; }
            set {
                _id = value;
            }
        }

        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
            }
        }

        public override string ToString()
        {
            return _name;
        }

        public bool Equals(Shaft shaft)
        {
            System.Diagnostics.Debug.WriteLine("Calling from object.Equals");
           // Shaft shaft = obj as Shaft;
            if (null != shaft)
            {
                System.Diagnostics.Debug.WriteLine("Equals called for " + this.Name + ". Compared with " + shaft.Name);
            }
            else
            {
                System.Diagnostics.Debug.WriteLine("Equals called for " + this + ". Compared with " + shaft);
            }
            return base.Equals(shaft);
        }
    }
}

Это показывает, что выпадающий список не освобождает объекты, связанные с Itemsource, даже если список пуст. Пока мы не реализуем IEquatable.

Есть идеи, почему это так?

1 Ответ

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

Поведение Button_Click одинаково для обеих реализаций.Как вы узнали, что Object.Equals не было обращений, если вы не переопределили его во втором случае?

Что касается не "освобождения" объектов, то это похоже на известную проблему WPF: http://support.microsoft.com/kb/938416

В качестве обходного пути вы можете сделать одно из следующих действий:

  • вызвать метод Collection.Clear вместо установки ссылки на коллекцию в null
  • использовать ObservableCollection вместо Collection
...