Just to illustrate how approach suggested by @mikehc will work take a look at the following working code sample:
FeedViewModel.cs - Notice that it use timer for periodical refresh (1 sec in this code or whatever you like/need in yours) of its title with information from its child's synchronization status. This is much simpler solution rather than subscribing to events from each of its child to be notified when it will be synchronized, deal with adding new and removing old child items and so on:
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows.Threading;
namespace WpfApplication11
{
public class FeedViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = delegate {};
DispatcherTimer timer =
new DispatcherTimer(DispatcherPriority.Background);
private string feedName;
public string FeedName
{
get { return feedName; }
set
{
feedName = value;
PropertyChanged(this,
new PropertyChangedEventArgs("FeedName"));
PropertyChanged(this,
new PropertyChangedEventArgs("FeedTitle"));
}
}
public ObservableCollection<ItemViewModel> FeedItems { get; set; }
public string FeedTitle
{
get
{
return string.Format("({0}/{1}) {2}",
FeedItems.Count(item => item.IsSynchronized),
FeedItems.Count,
FeedName);
}
}
public FeedViewModel()
{
FeedItems = new ObservableCollection<ItemViewModel>();
timer.Interval = TimeSpan.FromMilliseconds(1000);
timer.Tick += (sender, args) =>
PropertyChanged(this,
new PropertyChangedEventArgs("FeedTitle"));
timer.Start();
}
}
}
ItemViewModel.cs:
using System.ComponentModel;
namespace WpfApplication11
{
public class ItemViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = delegate {};
private string itemName;
private bool isSynchronized;
public string ItemName
{
get { return itemName; }
set
{
itemName = value;
PropertyChanged(this, new PropertyChangedEventArgs("ItemName"));
}
}
public bool IsSynchronized
{
get { return isSynchronized; }
set
{
isSynchronized = value;
PropertyChanged(this,
new PropertyChangedEventArgs("IsSynchronized"));
}
}
}
}
DataSetCreator.cs - this is just a two mocks - DataSet and DataSetCreator for classes that you mentioned in your code, so feel free to use you own):
using System.Collections.ObjectModel;
namespace WpfApplication11
{
public class DataSet
{
public ObservableCollection<FeedViewModel> Feeds { get; private set; }
public DataSet()
{
Feeds = new ObservableCollection<FeedViewModel>
{
new FeedViewModel
{
FeedName = "Feed #1",
FeedItems = new ObservableCollection<ItemViewModel>
{
new ItemViewModel
{
ItemName = "Item #1.1",
IsSynchronized = true
},
new ItemViewModel
{
ItemName = "Item #1.2",
IsSynchronized = true
},
new ItemViewModel
{
ItemName = "Item #1.3",
IsSynchronized = false
},
}
},
new FeedViewModel
{
FeedName = "Feed #2",
FeedItems = new ObservableCollection<ItemViewModel>
{
new ItemViewModel
{
ItemName = "Item #2.1",
IsSynchronized = true
},
new ItemViewModel
{
ItemName = "Item #2.2",
IsSynchronized = true
},
}
},
new FeedViewModel
{
FeedName = "Feed #3",
FeedItems = new ObservableCollection<ItemViewModel>
{
new ItemViewModel
{
ItemName = "Item #3.1",
IsSynchronized = false
},
new ItemViewModel
{
ItemName = "Item #3.2",
IsSynchronized = false
},
}
}
};
}
}
public class DataSetCreator
{
public DataSet CreateDataSet()
{
return new DataSet();
}
}
}
and, finally, MainWindow.xaml - updated to use the mock class DataSetCreator.cs from above:
<Window x:Class="WpfApplication11.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApplication11"
mc:Ignorable="d" Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:ItemViewModel x:Key="DesignItemViewModel" />
<local:FeedViewModel x:Key="DesignFeedViewModel" />
<ObjectDataProvider x:Key="dataSetProvider"
ObjectType="{x:Type local:DataSetCreator}"
MethodName="CreateDataSet" />
<DataTemplate x:Key="ItemTemplate">
<StackPanel Orientation="Horizontal"
d:DataContext="{StaticResource DesignItemViewModel}">
<TextBlock Text="{Binding Path=ItemName}" />
<CheckBox IsChecked="{Binding Path=IsSynchronized}"
Margin="25,0,0,0"
Content=" is synchronized?"/>
</StackPanel>
</DataTemplate>
<HierarchicalDataTemplate x:Key="FeedTemplate"
ItemsSource="{Binding Path=FeedItems}"
ItemTemplate="{StaticResource ItemTemplate}">
<StackPanel Orientation="Horizontal"
d:DataContext="{StaticResource DesignFeedViewModel}">
<TextBlock Text="{Binding Path=FeedTitle}" />
</StackPanel>
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<TreeView DataContext="{StaticResource dataSetProvider}"
d:DataContext="{StaticResource dataSetProvider}"
ItemsSource="{Binding Path=Feeds}"
ItemTemplate="{StaticResource FeedTemplate}" />
</Grid>
</Window>