【问题标题】:WPF Style/Template gets applied only to the last added elementWPF 样式/模板仅应用于最后添加的元素
【发布时间】:2016-07-06 07:58:15
【问题描述】:

我有一个从ContentControl 派生的简单控件,代码如下:

public class HeaderFooterControl : ContentControl
{
    static HeaderFooterControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(HeaderFooterControl), new FrameworkPropertyMetadata(typeof(HeaderFooterControl)));
    }

    public object Header
    {
        get { return (object)GetValue(HeaderProperty); }
        set { SetValue(HeaderProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Header.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty HeaderProperty =
        DependencyProperty.Register("Header", typeof(object), typeof(HeaderFooterControl));

    public object Footer
    {
        get { return (object)GetValue(FooterProperty); }
        set { SetValue(FooterProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Footer.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty FooterProperty =
        DependencyProperty.Register("Footer", typeof(object), typeof(HeaderFooterControl));



    public string HeaderText
    {
        get { return (string)GetValue(HeaderTextProperty); }
        set { SetValue(HeaderTextProperty, value); }
    }

    // Using a DependencyProperty as the backing store for HeaderText.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty HeaderTextProperty =
        DependencyProperty.Register("HeaderText", typeof(string), typeof(HeaderFooterControl));



    public string FooterText
    {
        get { return (string)GetValue(FooterTextProperty); }
        set { SetValue(FooterTextProperty, value); }
    }

    // Using a DependencyProperty as the backing store for FooterText.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty FooterTextProperty =
        DependencyProperty.Register("FooterText", typeof(string), typeof(HeaderFooterControl));


}

它具有可自定义的页眉和页脚属性,因此用户可以在其中附加任何控件。

这个应用程序中唯一的窗口是这样定义的:

<Window x:Class="CustomControlTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:CustomControlTest"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Style TargetType="{x:Type local:HeaderFooterControl}" x:Key="DefaultHeaderFooterStyle">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:HeaderFooterControl}">
                        <Grid Background="Pink">
                            <Grid.RowDefinitions>
                                <RowDefinition/>
                                <RowDefinition/>
                                <RowDefinition/>
                            </Grid.RowDefinitions>
                            <ContentPresenter Content="{Binding Header, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"/>
                            <ContentPresenter Grid.Row="1"/>
                            <ContentPresenter Content="{Binding Footer, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" Grid.Row="2"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <Style TargetType="{x:Type local:HeaderFooterControl}" BasedOn="{StaticResource DefaultHeaderFooterStyle}">
            <Style.Setters>
                <Setter Property="Header">
                    <Setter.Value>
                        <TextBlock Text="{Binding HeaderText, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:HeaderFooterControl}}}" Background="Yellow" HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
                    </Setter.Value>
                </Setter>
                <Setter Property="Footer">
                    <Setter.Value>
                        <TextBlock Text="{Binding FooterText, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:HeaderFooterControl}}}" Background="Green" HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
                    </Setter.Value>
                </Setter>
            </Style.Setters>
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <local:HeaderFooterControl HeaderText="H1" FooterText="F1" Margin="10"/>
        <local:HeaderFooterControl HeaderText="H2" FooterText="F2" Grid.Row="1" Margin="10"/>
        <local:HeaderFooterControl HeaderText="H3" FooterText="F3" Grid.Row="2" Margin="10"/>
    </Grid>
</Window>

此窗口的资源为我的自定义控件定义了 2 种样式。自定义控件显示页眉、主要内容和页脚。默认情况下页眉/页脚是TextBlocks,它的Text 属性绑定到HeaderTextFooterText 属性HeaderFooterControl。问题是只有最后添加的HeaderFooterControl 显示任何内容。为什么会这样?

【问题讨论】:

  • 内容是指页眉/页脚文本是否正确?
  • 首先 - 使用 TemplateBindings。也尝试创造一种组合风格。它会起作用吗?

标签: c# wpf custom-controls


【解决方案1】:

到目前为止,我发现的唯一解决方案是将页眉和页脚部分的内容移动到资源中,然后使用 StaticResource 扩展从 xaml 代码中引用这些资源。所有内容都是UIElements,因此每个实例都应该设置x:Shared="False" 属性,以便在VisualTree 中每次需要它时都会创建它。另请查看此答案,这意味着与https://stackoverflow.com/a/8702180/371967 描述的行为相同

<Window x:Class="CustomControlTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:CustomControlTest"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Style TargetType="{x:Type local:HeaderFooterControl}" x:Key="DefaultHeaderFooterStyle">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:HeaderFooterControl}">
                        <Grid Background="Pink">
                            <Grid.RowDefinitions>
                                <RowDefinition/>
                                <RowDefinition/>
                                <RowDefinition/>
                            </Grid.RowDefinitions>
                            <ContentPresenter Content="{Binding Header, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"/>
                            <ContentPresenter Grid.Row="1"/>
                            <ContentPresenter Content="{Binding Footer, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" Grid.Row="2"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <TextBlock x:Key="DefaultHeaderContent" Text="{Binding HeaderText, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:HeaderFooterControl}}}" Background="Yellow" HorizontalAlignment="Stretch" VerticalAlignment="Center" x:Shared="False"/>
        <TextBlock x:Key="DefaultFooterContent" Text="{Binding FooterText, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:HeaderFooterControl}}}" Background="Green" HorizontalAlignment="Stretch" VerticalAlignment="Center" x:Shared="False"/>

        <Style TargetType="{x:Type local:HeaderFooterControl}" BasedOn="{StaticResource DefaultHeaderFooterStyle}">
            <Style.Setters>
                <Setter Property="Header" Value="{StaticResource DefaultHeaderContent}"/>
                <Setter Property="Footer" Value="{StaticResource DefaultFooterContent}"/>
            </Style.Setters>
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <local:HeaderFooterControl HeaderText="H1" FooterText="F1" Margin="10"/>
        <local:HeaderFooterControl HeaderText="H2" FooterText="F2" Grid.Row="1" Margin="10"/>
        <local:HeaderFooterControl HeaderText="H3" FooterText="F3" Grid.Row="2" Margin="10"/>
    </Grid>
</Window>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-25
    • 1970-01-01
    • 2015-01-09
    • 2012-08-03
    • 2016-05-03
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    相关资源
    最近更新 更多