Reputation: 5
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
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
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