C# 如何将样式应用于在gridview下找到的第一个WPF ContentPresenter,但不应用于任何更深的WPF
我希望能够设置用于渲染GridView单元格的ContentPresenter的样式。但是,如果我通常将样式设置为以ContentPresenter为目标,那么它将以ContentPresenter中的ContentPresenter实例为目标,而我不希望这样做。我只想为找到的第一级内容演示者设置样式 这可能吗?像这样的C# 如何将样式应用于在gridview下找到的第一个WPF ContentPresenter,但不应用于任何更深的WPF,c#,.net,wpf,C#,.net,Wpf,我希望能够设置用于渲染GridView单元格的ContentPresenter的样式。但是,如果我通常将样式设置为以ContentPresenter为目标,那么它将以ContentPresenter中的ContentPresenter实例为目标,而我不希望这样做。我只想为找到的第一级内容演示者设置样式 这可能吗?像这样的 <Style Target="GridView"> <Style.Resource> <Style Target="Con
<Style Target="GridView">
<Style.Resource>
<Style Target="ContentPresenter" Depth=1>
<Setter Property="Margin" Value="1"/>
</Style>
</Style.Resources>
</Style>
其中Depth=1是一个虚构的属性。您可以使用DataTemplateSelector来实现这一点,方法是为ContentPresenter设置一个样式,并确保它使用了默认的样式 我的例子简化了,没有使用GridView,但概念是一样的 如果您具有以下DataTemplateSelector:
public class DepthTemplateSelector : DataTemplateSelector
{
public DataTemplate InDepthTemplate { get; set; }
public Type Type { get; set; }
public int Depth { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var next = container;
int itemsControlCount = 0;
while (VisualTreeHelper.GetParent(next) != null)
{
var current = VisualTreeHelper.GetParent(next);
if (current.GetType() == this.Type)
{
itemsControlCount++;
}
next = current;
}
if (itemsControlCount <= this.Depth)
{
return this.InDepthTemplate;
}
return base.SelectTemplate(item, container);
}
}
然后在XAML中将其与您希望用于内容演示者(深度小于某一深度)的任何模板连接起来:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:w="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<w:DepthTemplateSelector x:Key="DepthTemplateSelector" Depth="2" Type="{x:Type ContentPresenter}">
<w:DepthTemplateSelector.InDepthTemplate>
<DataTemplate DataType="{x:Type w:Model}">
<StackPanel>
<TextBlock Text="{Binding Description}" Foreground="Red" />
<ItemsControl ItemsSource="{Binding Models}" Margin="20,0,0,0" />
</StackPanel>
</DataTemplate>
</w:DepthTemplateSelector.InDepthTemplate>
</w:DepthTemplateSelector>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="ContentTemplateSelector" Value="{StaticResource DepthTemplateSelector}" />
</Style>
<DataTemplate DataType="{x:Type w:Model}">
<StackPanel>
<TextBlock Text="{Binding Description}" />
<ItemsControl ItemsSource="{Binding Models}" Margin="20,0,0,0" />
</StackPanel>
</DataTemplate>
</Window.Resources>
<Window.DataContext>
<w:ViewModel />
</Window.DataContext>
<ListView ItemsSource="{Binding Models}" />
</Window>
因此XAML创建和配置DataTemplateSelector,但也通过设置默认ContentPresenter样式来确保所有ContentPresenter都使用它
这将为您提供以下效果,深度设置为2:
这基于以下视图模型,该模型使用递归结构来说明这一点:
public class ViewModel
{
public ViewModel()
{
this.Models = new List<Model>
{
new Model
{
Description = "ModelA",
Models = new List<Model>
{
new Model { Description = "ModelA1" },
new Model { Description = "ModelA2" }
}
},
new Model
{
Description = "ModelB",
Models = new List<Model>
{
new Model { Description = "ModelB1" },
new Model
{
Description = "ModelB2",
Models = new List<Model>
{
new Model { Description = "ModelB2i" },
new Model { Description = "ModelB2ii" }
}
}
}
}
};
}
public List<Model> Models { get; set; }
}
public class Model
{
public string Description { get; set; }
public List<Model> Models { get; set; }
}