0

コンボ ボックスの作業中に、有線の問題が見つかりました。Xamlは次のようになります

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

Itemsource が Shaft (オブジェクト) のリストにバインドされており、selectedItem がリストの 1 つであるとします。

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

そして、このリストをnullにしようとしました(Button_Clickを参照してください).Comboboxは、リストの各オブジェクトの.Equalsを呼び出して、最後に選択したオブジェクトを比較します。私の期待では、.equals を呼び出して SelectedItem を null に設定するべきではありません。

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

Shaft に IEquatable を実装し、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);
        }
    }
}

これは、リストが null の場合でも、コンボボックスが Itemsource にバインドされたオブジェクトを解放していないことを示しています。IEquatable を実装するまで。

なぜそれがそのようなものなのか、何か考えはありますか?

4

1 に答える 1

0

Button_Click 時の動作は、両方の実装で同じです。2 番目のケースで Object.Equals をオーバーライドしなかった場合、Object.Equals への呼び出しがないことをどうやって知りましたか?

オブジェクトを「解放」しないことに関しては、これは WPF の既知の問題のようです: http://support.microsoft.com/kb/938416

回避策として、次のいずれかを実行できます。

  • コレクション参照を null に設定する代わりに Collection.Clear メソッドを呼び出す
  • Collection の代わりに ObservableCollection を使用する
于 2011-03-14T12:38:28.690 に答える