WPF - 使用变量/参数创建可重用的样式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19398450/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF - Create reusable style with variables/parameters
提问by Farsen
I have an WPF application which contains several TabItems. Each TabItem is different from each other, with a text and an icon.
我有一个包含多个 TabItem 的 WPF 应用程序。每个 TabItem 彼此不同,有一个文本和一个图标。
This is how the TabItem′s style is defined:
TabItem 的样式是这样定义的:
<TabItem.Style>
<Style TargetType="TabItem">
<Setter Property="Header">
<Setter.Value>
<StackPanel Orientation="Horizontal">
<Image Margin="10,0,0,0" Height="40" Width="40" Source="Images/IconLeafGrey.png"/>
<TextBlock Text="This is the heading" VerticalAlignment="Center" Style="{StaticResource Heading2}" Margin="10,0,0,0"/>
</StackPanel>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border Name="Border" BorderBrush="Black" BorderThickness="1,1,1,1" CornerRadius="6,6,0,0" >
<Border.Background>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#f5f7f8" Offset="0.0" />
<GradientStop Color="#c5d0dd" Offset="1.0" />
</LinearGradientBrush>
</Border.Background>
<ContentPresenter Name="ContentSite" VerticalAlignment="Center" HorizontalAlignment="Left" ContentSource="Header" Margin="5,2,0,2"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" TargetName="Border">
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#ebedee" Offset="0.0" />
<GradientStop Color="#88a2bd" Offset="1.0" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Header">
<Setter.Value>
<StackPanel Orientation="Horizontal">
<Image Margin="10,0,0,0" Height="40" Width="40" Source="Images/IconLeaf.png"/>
<TextBlock Text="This is the heading" VerticalAlignment="Center" Style="{StaticResource Heading2}" Margin="10,0,0,0"/>
</StackPanel>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</TabItem.Style>
So instead of writing this XAML markup for each TabItem, I would like to define this style once in my ResourceDictionary, but with the Icon and the Text property as optional parameters. So I afterwards could define a TabItem like this:
因此,我不想为每个 TabItem 编写这个 XAML 标记,而是想在我的 ResourceDictionary 中定义一次这种样式,但使用 Icon 和 Text 属性作为可选参数。所以我之后可以像这样定义一个 TabItem:
<TabItem Width="250" Height="60" Style="{StaticResource CustomTabItem}" >
I′ve read that it isnt directly possible for a style to accept parameters like this, but it should be posible with some sort of binding. I havent found out exactly how though, so I really hope you can help.
我已经读到样式不能直接接受这样的参数,但它应该可以通过某种绑定来实现。我还没有找到确切的方法,所以我真的希望你能帮忙。
Kind regards.
亲切的问候。
采纳答案by Nitin
One way of doing it would be, if you have fixed number of TabItemsand you dont want to generate the TabItemsthrough ItemsSourceBindingon TabControl. Then in your TabItem.Styleyou can use Resourcekeys to get the Text and Source like:
这样做的一种方法是,如果您有固定数量的TabItems并且不想在 TabControl 上生成TabItems直通ItemsSourceBinding。然后在您TabItem.Style可以使用Resource键来获取文本和源,如:
<StackPanel Orientation="Horizontal">
<Image Margin="10,0,0,0" Height="40" Width="40" Source="{DynamicResource Image1}"/>
<TextBlock Text="{DynamicResource Header}" VerticalAlignment="Center" Style="{StaticResource Heading2}" Margin="10,0,0,0"/>
</StackPanel>
and for your TabItems you can define these resources:
对于您的 TabItems,您可以定义这些资源:
<TabItem Width="250" Height="60" Style="{StaticResource CustomTabItem}">
<TabItem.Resources>
<System:String x:Key="Header">TabItem1</System:String>
<System:String x:Key="Image1">image/1.png</System:String>
<System:String x:Key="Image2">image/2.png</System:String>
</TabItem.Resources>
</TabItem>
<TabItem Width="250" Height="60" Style="{StaticResource CustomTabItem}">
<TabItem.Resources>
<System:String x:Key="Header">TabItem2</System:String>
<System:String x:Key="Image1">image/3.png</System:String>
<System:String x:Key="Image2">image/4.png</System:String>
</TabItem.Resources>
</TabItem>
Also you will need to update your Styleto set the HeaderTemplateinstead of Header
您还需要更新您Style的设置HeaderTemplate而不是Header
<Style x:Key="CustomTabItem" TargetType="TabItem">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image x:Name="HeaderImage" Margin="10,0,0,0" Height="40" Width="40" Source="Images/IconLeafGrey.png"/>
<TextBlock Text="{DynamicResource Header}" VerticalAlignment="Center" Margin="10,0,0,0"/>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType={x:Type TabItem}}}" Value="true">
<Setter TargetName="HeaderImage" Property="Source" Value="Images/IconLeaf.png"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border Name="Border" BorderBrush="Black" BorderThickness="1,1,1,1" CornerRadius="6,6,0,0" >
<Border.Background>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#f5f7f8" Offset="0.0" />
<GradientStop Color="#c5d0dd" Offset="1.0" />
</LinearGradientBrush>
</Border.Background>
<ContentPresenter Name="ContentSite" VerticalAlignment="Center" HorizontalAlignment="Left" ContentSource="Header" Margin="5,2,0,2"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" TargetName="Border">
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#ebedee" Offset="0.0" />
<GradientStop Color="#88a2bd" Offset="1.0" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
回答by Sheridan
You just need to set the TabItem.DataContextto an object that contains values for your TextBlockand Imagecontrols:
您只需要将 设置为TabItem.DataContext包含您TextBlock和Image控件的值的对象:
In code:
在代码中:
public class TabItemData
{
public string ImageSource { get; set; }
public string Heading { get; set; }
}
In your Stylein XAML:
在您Style的 XAML 中:
<StackPanel Orientation="Horizontal">
<Image Margin="10,0,0,0" Height="40" Width="40" Source="{Binding ImageSource}"/>
<TextBlock Text="{Binding Heading}" VerticalAlignment="Center"
Style="{StaticResource Heading2}" Margin="10,0,0,0"/>
</StackPanel>
In your view model:
在您的视图模型中:
public class TabControlViewModel
{
public TabControlViewModel()
{
TabItemData = new TabItemData() { Header = "Some header",
ImageSource = "Images/IconLeafGrey.png" };
}
public TabItemData TabItemData { get; set; }
}
In XAML:
在 XAML 中:
<TabItem DataContext="{Binding TabItemData}">
...
</TabItem>
Of course, I've left out some initialisation of the data objects and the INotifyPropertyChangedinterface which you should implement, but I hope you get the idea.
当然,我省略了一些数据对象的初始化和INotifyPropertyChanged您应该实现的接口,但我希望您能理解。

