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

时间:2013-10-16 08:23:16

标签: wpf styles

我有一个包含多个TabItem的WPF应用程序。每个TabItem都彼此不同,带有文本和图标。

这是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}" >

我已经读过,样式不可能直接接受这样的参数,但它应该是某种绑定的可能。我还没有找到具体的方法,所以我真的希望你能提供帮助。

亲切的问候。

2 个答案:

答案 0 :(得分:3)

您只需将TabItem.DataContext设置为包含TextBlockImage控件值的对象:

在代码中:

public class TabItemData
{
    public string ImageSource { get; set; }
    public string Heading { get; set; }
}

在XAML的Style中:

<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>

在您的视图模型中:

public class TabControlViewModel
{
    public TabControlViewModel()
    {
        TabItemData = new TabItemData() { Header = "Some header", 
            ImageSource = "Images/IconLeafGrey.png" };
    }

    public TabItemData TabItemData { get; set; }
}

在XAML中:

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

当然,我已经省略了一些数据对象的初始化以及你应该实现的INotifyPropertyChanged接口,但我希望你明白这一点。

答案 1 :(得分:3)

如果您有TabItems的固定数量,并且您不希望在TabControl上生成TabItemsItemsSource Binding,那么这样做的一种方法就是这样做。然后在您的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>

您的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>

此外,您需要更新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>