WPF-使用变量/参数创建可重用样式

WPF-使用变量/参数创建可重用样式,wpf,styles,Wpf,Styles,我有一个WPF应用程序,它包含几个选项卡项。每个选项卡项都不同,有一个文本和一个图标 以下是TabItem样式的定义方式: <TabItem.Style> <Style TargetType="TabItem"> <Setter Property="Header"> <Setter.Value>

我有一个WPF应用程序,它包含几个选项卡项。每个选项卡项都不同,有一个文本和一个图标

以下是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>

因此,我不想为每个TabItem编写这个XAML标记,而是想在我的ResourceDictionary中定义一次这个样式,但将Icon和Text属性作为可选参数。之后我可以定义一个TabItem,如下所示:

<TabItem Width="250" Height="60" Style="{StaticResource CustomTabItem}" >

我已经读到,样式不可能直接接受这样的参数,但它应该可以通过某种绑定实现。不过我还没有弄清楚具体的方法,所以我真的希望你能帮我


问候。

您只需将
选项卡项.DataContext
设置为包含
文本块
图像
控件值的对象:

代码:

public class TabItemData
{
    public string ImageSource { get; set; }
    public string Heading { get; set; }
}
在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>
在XAML中:

<TabItem DataContext="{Binding TabItemData}">
    ...
</TabItem>

...

当然,我省略了一些数据对象的初始化和您应该实现的INotifyPropertyChanged接口,但我希望您能理解。

一种方法是,如果您有固定数量的
选项卡项
,并且不希望通过选项卡控件上的
项源
绑定
生成
选项卡项
。然后在
选项卡item.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>

您可以创建只覆盖图标和文本属性的主样式。非常感谢,它似乎正在工作。。。几乎!问题是,当我在两个或多个选项卡项上设置样式时,VisualStudio会警告我“指定的元素已经是另一个元素的逻辑子元素。请先断开它的连接”。如果我运行应用程序,它会失败,因为'Set property'System.Windows.FrameworkElement.Style'抛出了一个异常。我处理了它,如果我从样式中删除整个标题部分,错误就会消失。。。有什么想法吗?你能分享一下你是如何定义资源的吗?我现在更新了我如何定义资源的问题。不知道这是不是一种方法,但是注释不能支持这么多字符?实际上我想知道您是如何定义TabItem的。参考资料。。。您已将代码两次添加到TabItem StyleAh抱歉。这就是我如何定义TabItem:TabItem1的
    <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>
     <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>
     <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>