对象属性更改,但绑定的ListBox不更新

时间:2010-12-18 20:42:32

标签: c# winforms data-binding

我有一个复杂对象列表,以及一个使用BindingSource绑定到此List的ListBox。当用户选择列表框中的项目时,他可以通过PropertyGrid编辑它的属性,并通过TextBox单独编辑它的文本。当通过PropertyGrid更改属性时,会调用BindingSource的CurrentItemChanged,但是当用户刚编辑TextBox时我在更新DataBinding时遇到问题

以下是一些可以更好地解释我的情况的代码:


class Song
{
    public string Title{get;set}
    [Browsable(false)]
    public string Text{get;set;}
    ...
}

class SongBook
{
    public List Songs {get;set;}
    ...
}

// Initialization: we are setting ListBox's DataSource to songBookBindingSource
private void InitializeComponent()
{
    ...
    this.allSongsList.DataSource = this.songBookBindingSource;
    ...
}

// We create new SongBook object, and set BindingSource's DataSource to 
// list of songs in songbook
private void OpenSongBook()
{
    ...
    currentSongBook.Deserialize( path );
    songBookBindingSource.DataSource = currentSongBook.Songs;
}

// When user selects a song in ListBox, we try to edit it's properties
private void allSongsList_SelectedValueChanged(object sender, EventArgs e)
{
    ...
    songProps.SelectedObject = allSongsList.SelectedItem;
    songTextEdit.Text = (allSongsList.SelectedItem as Song).Text;
}

// This get called whenever user changes something in TextBox.
// If it does, we want to mark song as Unsaved and refresh
// ListBox, so it would display a nice little "*" next to it!
private void songTextEdit_TextChanged(object sender, EventArgs e)
{
    currentSong.Text = editSongTextBox.Text;
    currentSong.Unsaved = true;

    // As far as I understand, this SHOULD make ListBox bound to songBookBindingSource
    // update its items. But it does not! How do I make it understand that data changed?
    songBookBindingSource.RaiseListChangedEvents = true;

    // And if I do this, ListBox DOES gets updated, but something also inserts A COPY OF CURRENT ITEM
    // into it. If I select it, allSongsList.SelectedItem throws "Out of bounds" exception. As far
    // as I understand, it gets added only to ListBox, but NOT to underlying List. But why is it 
    // even getting added at all?!
    // songBookBindingSource.ResetCurrentItem();
}

我觉得.NET Framework讨厌我:)

1 个答案:

答案 0 :(得分:2)

您的对象需要实现INotifyPropertyChanged,这样当属性更改时绑定将刷新:

class Song : INotifyPropertyChanged
{
    private string _title;
    public string Title
    {
        get { return _title; }
        set
        {
            _title = value;
            OnPropertyChanged("Title");
        }
    }

    private string _text;
    [Browsable(false)]
    public string Text
    {
        get { return _text; }
        set
        {
            _text = value;
            OnPropertyChanged("Text");
        }
    }
    ...


    public event PropertyChangedEventHandler PropertyChanged;

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