pyridot
pyridot

Reputation: 5

binding observable collection to listbox item source doesnt update unless onPropertyChanged fired

I am trying to display a list of filenames of uploaded files using a listbox. I have buttons to upload, open and delete files in the list box. I am using the mvvm pattern and have bound the itemsource to an observable collection. When ever I modify the collection (i.e: upload or del) the listbox doesnt refresh to reflect changes when collection is changed. I am certain that the way I have implemented this is bad. At this point I am totally confused as to how a observable collection notifies changes. Below is my code:

 <ListBox x:Name="Listbox1"    
          SelectedItem="{Binding SelectedFile}" 
          SelectedIndex="{Binding SelectedIndexNum}"
          ItemsSource="{Binding Path=FileNames, UpdateSourceTrigger=PropertyChanged}">                            
 </ListBox>
 <Button Content="UploadFile" 
         Command="{Binding Path=UploadFileCommand}" 
 </Button>

 <Button Content="Delete File" 
         Command="{Binding Path=DeleteFileCommand}" 
 </Button>

The view model property:

 public ObservableCollection<string> FileNames
    {
        get
        {
            if (this.SomeDataStruc.UploadedFileDataCollection == null || this.SomeDataStruc.UploadedFileDataCollection .Count() <= 0)
            {
                return new ObservableCollection<string>();
            }
            else
            {
                var uploadedFileList = this.SomeDataStruc.UploadedFileDataCollection .Where(r => r.Id == this.SomeDataStruc.Id);
                var filenames = new ObservableCollection<string>(uploadedFileList.Select(c => c.FileName));//.ToList();
                return filenames;
            }
        }          
    }

Please note that the SomeDataStruc has an observable collection. this UploadedFileData has many fields out of which I am displaying only the filename in the listbox.

 private void DeleteReport(object parameter)
    {
        this.UploadedFileDataCollection[_selectedIndex].Status = DataStatusEnum.Deleted;

        this.SomeDataStruc.UploadedFileDataCollection.RemoveAt(_selectedIndex);


        this.OnPropertyChanged("FileNames"); // i need to do this...Listbox doesnt update without this.


    }

WHat am i doing wrong. should i be handling collectionchanged event? if so why? isnt that the point of observable collection....that it notifies on its own?

I have checked many similar topics. but that doesnt seem to clear my confusion. Please help me out.

Upvotes: 0

Views: 1818

Answers (2)

user1064519
user1064519

Reputation: 2190

this is the right behavior, since you dont remove anything from FileNames,just from UploadedFileDataCollection which is a regular list. so clearly you need to raise propertyChanged to teel the UI to recreate FileNames list based on the remained items in UploadedFileDataCollection

Upvotes: 0

Phil
Phil

Reputation: 43021

Your problem is that the FileNames property is always returning a new ObservableCollection.

If you had code like this:

private ObservableCollection<string> _fileNames;

public ObservableCollection<string> FileNames
{
    get
    {
        if(_fileNames == null) 
        { 
            _fileNames = new ObservableCollection<string>(); 
        }
        return _fileNames;
    }
}

Then any changes to the FileNames collection would cause notifications and your UI to be updated.

e.g.

private void LoadFileNames()
{
    FileNames.Clear();
    foreach( ... ) 
    { 
        FileNames.Add(...);  // collection changed notification here
    }
}

Since you are changing the collection every time FileNames is used (which is inefficient) you need to call this.OnPropertyChanged("FileNames"); to tell the UI that the whole collection has been replaced.

Upvotes: 2

Related Questions