I was using .Net 4.0 and had a Dictionary
in my code like the one below
public Dictionary<DirectoryInfo, ObservableCollection<Media>> FoldersDictionary
I am using this dictionary of to display the folders from windows directory in a surface list box. DirectoryInfo
will contain the directory information about folders e.g their names and Media
class will contain the data inside these folders.
When I add or remove items from the ObservableCollection
in my Dictionary
, WPF threw this warning at me:
Collection of type 'System.Collections.Generic.Dictionary`2[[System.IO.DirectoryInfo,
mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],
[System.Collections.ObjectModel.ObservableCollection`1[[Media, ViewModel,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System, Version=4.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089]]' has been changed without raising
a CollectionChanged event. Support for this is incomplete and inconsistent,
and will be removed completely in a future version of WPF. Consider either (a)
implementing INotifyCollectionChanged, or (b) avoiding changes to this type of
collection`.
However I ignored this warning as my output was showing up alright. Yesterday I upgraded to .Net 4.5.1 on Windows 7 and ran this code. The warning was still the same but now every time I refresh my dictionary (meaning clearing it and then adding new stuff to ObservableCollection
), the last ObservableCollection
item is never visible on my UI. I debugged my code and found out that the Dictionary
infact still has the last item added in it, its just that it is not being displayed on my WPF XAML UI. I wondered may be this behavior is due to the warning I see. I implemented the following CollectionChanged
event to my code:
private void OnUrlChanged(string newUrl)
{
if (string.IsNullOrEmpty(newUrl))
return;
var directoryInfo = new DirectoryInfo(newUrl);
DirectoryInfo[] directoryInfos = directoryInfo.GetDirectories();
if (directoryInfos.Any())
{
if (FoldersDictionary != null && FoldersDictionary.Any())
{
FoldersDictionary.Clear();
}
FoldersDictionary = null;
FoldersDictionary = new Dictionary<DirectoryInfo, ObservableCollection<Media>>();
LoadFolders(FoldersDictionary, directoryInfos);
}
}
private void LoadFolders( Dictionary<DirectoryInfo, ObservableCollection<Media>> Folders, IEnumerable<DirectoryInfo> directoryInfos)
{
foreach (DirectoryInfo item in directoryInfos)
{
ObservableCollection<Media> medias = LoadMedias(item.FullName);
//new code starts here
medias.CollectionChanged+=new System.Collections.Specialized.NotifyCollectionChangedEventHandler(medias_CollectionChanged);
//new code ends here
if (medias != null)
{
Folders.Add(item, medias);
}
}
}
//new code starts here
void medias_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
//do nothing
}
//new code ends here
My Dictionary
PropertyChanged
is given as:
public const string FoldersDictionaryPropertyName = "FoldersDictionary";
private Dictionary<DirectoryInfo, ObservableCollection<Media>> _foldersDictionary;
public Dictionary<DirectoryInfo, ObservableCollection<Media>> FoldersDictionary
{
get { return _foldersDictionary; }
set
{
if (_foldersDictionary == value)
{
return;
}
Dictionary<DirectoryInfo, ObservableCollection<Media>> oldValue = _foldersDictionary;
_foldersDictionary = value;
RaisePropertyChanged(FoldersDictionaryPropertyName);
}
}
This is the XAML I am using.
<Grid Height="180">
<s:SurfaceListBox x:Name="xFoldersListBox"
Background="{x:Null}"
ItemContainerStyle="{StaticResource SurfaceListBoxItemSquareStyle}"
ItemsSource="{Binding FoldersDictionary}"
ItemTemplate="{StaticResource FolderDataTemplate}"
SelectedValuePath="Value"
Template="{StaticResource SurfaceListBoxHorizontalTemplate}" />
</Grid>
<DataTemplate x:Key="FolderDataTemplate">
<s:SurfaceToggleButton IsChecked="{Binding IsSelected,
Mode=TwoWay,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type s:SurfaceListBoxItem}}}" Style="{StaticResource ToggleButtonStyle}">
<TextBlock Text="{Binding Path=Key.Name}"
TextAlignment="Center"
TextWrapping="Wrap" />
</s:SurfaceToggleButton>
</DataTemplate>
However I am still getting the same warning as before and further more I cant see my last folder in my dictionary being displayed at all when I clear and repopulate my Dictionary
. Any idea what may be causing this behaviour?