我正在尝试显示这种层次结构:
public interface IProgressIndicator
{
CancellationToken CancellationToken { get; }
string Name { get; set; }
}
public interface IPercentageProgressIndicator : IProgressIndicator
{
int ProgressPercentage { get; set; }
}
public interface ICountProgressIndicator : IProgressIndicator
{
int ProgressPercentage { get; }
int CurValue { get; set; }
int MaxValue { get; set; }
}
public interface ICompositeProgressIndicator : ICountProgressIndicator
{
ObservableCollection<IProgressIndicator> SubProgressItems { get; }
void MarkAsComplete(IProgressIndicator progress);
IPercentageProgressIndicator CreatePercentageIndicator();
ICountProgressIndicator CreateCountIndicator();
ICompositeProgressIndicator CreateCompositeIndicator();
}
视图不应该假设层次结构已经到位;即应显示常规 IProgressIndicator(使用 ContentControl)并使用 DataTemplates 显示其他类型。
因此,当 IProgressIndicator 属于 ICompositeProgressIndicator 时,整个层次结构的根应该是 TreeView,根树视图项显示信息(如 ProgressPercentage 和 Name)。然后孩子应该再次显示为 IProgressIndicator 并使用 DataTemplates 选择适当的方式来查看其数据。嵌套的 ICompositeProgressIndicator 对象应该只添加另一个树视图项(而不是整个 TreeView)。
这就是我想出的。我不得不使用复杂的分层数据模板。我也在使用自定义 DataTemplateSelector,这很简单:
public class ProgressIndicatorTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var element = (container as FrameworkElement);
if (item is ICompositeProgressIndicator)
return element.FindResource("CompositeProgressIndicatorTemplate") as DataTemplate;
else if (item is ICountProgressIndicator)
return element.FindResource("CountProgressIndicatorTemplate") as DataTemplate;
else if (item is IPercentageProgressIndicator)
return element.FindResource("PercentageProgressIndicatorTemplate") as DataTemplate;
return null;
}
}
这是 XAML:
<StackPanel Grid.Row="2" Margin="5" Orientation="Vertical">
<StackPanel.Resources>
<editorUtil:ProgressIndicatorTemplateSelector x:Key="progressIndicatorTemplateSelector" />
<Converters:ObjectToTypeConverter x:Key="objectTypeConverter" />
<DataTemplate x:Key="CompositeProgressIndicatorTemplateBase">
<StackPanel Orientation="Vertical">
<TextBlock Text="CompositeProgressIndicatorTemplateBase" />
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding SubProgressItems.Count}" />
<TextBlock Text="{Binding Converter={StaticResource objectTypeConverter}}" Margin="5" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="CompositeProgressIndicatorTemplate">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Vertical">
<TextBlock Text="CompositeProgressIndicatorTemplateBase" />
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding SubProgressItems.Count}" />
<TextBlock Text="{Binding Converter={StaticResource objectTypeConverter}}" Margin="5" />
</StackPanel>
<TreeView Grid.Row="1" DataContext="{Binding}">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="true"/>
</Style>
</TreeView.ItemContainerStyle>
<TreeViewItem ItemsSource="{Binding SubProgressItems}" DataContext="{Binding}"
ItemTemplateSelector="{StaticResource progressIndicatorTemplateSelector}" IsExpanded="True">
<TreeViewItem.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<StackPanel.DataContext>
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type coreUtil:ICompositeProgressIndicator}}"
Path="."/>
</StackPanel.DataContext>
<TextBlock Text="CompositeProgressIndicatorTemplate" />
<ContentControl ContentTemplate="{StaticResource CompositeProgressIndicatorTemplateBase}">
<ContentControl.DataContext>
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type coreUtil:ICompositeProgressIndicator}}"
Path="."/>
</ContentControl.DataContext>
</ContentControl>
</StackPanel>
</DataTemplate>
</TreeViewItem.HeaderTemplate>
</TreeViewItem>
</TreeView>
</Grid>
</DataTemplate>
<HierarchicalDataTemplate DataType="{x:Type coreUtil:ICompositeProgressIndicator}" ItemsSource="{Binding Path=SubProgressItems}">
<ContentControl ContentTemplate="{StaticResource CompositeProgressIndicatorTemplateBase}" />
</HierarchicalDataTemplate>
<DataTemplate x:Key="CountProgressIndicatorTemplate" DataType="{x:Type coreUtil:ICountProgressIndicator}">
<Grid>
<ProgressBar Height="20" Value="{Binding ProgressPercentage, Mode=OneWay}" />
<TextBlock Margin="5" HorizontalAlignment="Center" Text="{Binding ProgressPercentage, Converter={StaticResource percentageConverter}, StringFormat=P}" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="PercentageProgressIndicatorTemplate" DataType="{x:Type coreUtil:IPercentageProgressIndicator}">
<Grid>
<ProgressBar Height="20" Value="{Binding ProgressPercentage, Mode=OneWay}" />
<TextBlock Margin="5" HorizontalAlignment="Center" Text="{Binding ProgressPercentage, Converter={StaticResource percentageConverter}, StringFormat=P}" />
</Grid>
</DataTemplate>
</StackPanel.Resources>
<ContentControl Content="{Binding ProgressIndicator}" ContentTemplateSelector="{StaticResource progressIndicatorTemplateSelector}">
</ContentControl>
</StackPanel>
这是它目前的样子:
根树视图项缺少 DataContext。