为了说明@mikehc 建议的方法如何工作,请查看以下工作代码示例:
FeedViewModel.cs - 请注意,它使用计时器来定期刷新其标题(此代码中为 1 秒,或者您喜欢/需要的任何内容)以及来自其子同步状态的信息。这是一个更简单的解决方案,而不是从每个子项订阅事件以在同步时得到通知,处理添加新的和删除旧的子项等等:
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();
}
}
}
项目视图模型.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 - 这只是两个模拟 - DataSet和DataSetCreator用于您在代码中提到的类,因此请随意使用您自己的):
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();
}
}
}
最后,MainWindow.xaml - 更新为使用上面的模拟类DataSetCreator.cs:
<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>