FindName在TabItem上失败

时间:2015-02-17 18:33:26

标签: c# wpf custom-controls

我已经创建了一个应用了XAML模板的自定义控件。在自定义控件中,我需要操作图像。为此,我尝试使用FindName在OnApplyTemplate中查找图像。但是,FindName返回null。代码:

public class QaTabItem : TabItem
{
    public static readonly DependencyProperty HotKeyProperty = DependencyProperty.Register("HotKey", typeof(string), typeof(QaTabItem));
    public static readonly DependencyProperty TabImageProperty = DependencyProperty.Register("TabImage", typeof(ImageSource), typeof(QaTabItem));
    public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(QaTabItem));
    public static readonly DependencyProperty CaptionProperty = DependencyProperty.Register("Caption", typeof(string), typeof(QaTabItem));
    public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register("Orientation", typeof(TabOrientation), typeof(QaTabItem));
    public static readonly DependencyProperty IndexProperty = DependencyProperty.Register("Index", typeof(double), typeof(QaTabItem));
    private Image arrowImage;

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        arrowImage = base.Template.FindName("ArrowImage", this) as Image;
    }
}

模板:

    <Style TargetType="{x:Type Image}" x:Key="ImageRotater">
    <Setter Property="RenderTransformOrigin" Value="0.5, 0.5" />
    <Setter Property="RenderTransform">
        <Setter.Value>
            <RotateTransform Angle="90" />
        </Setter.Value>
    </Setter>
</Style>
<Style TargetType="{x:Type controls:QaTabItem}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type controls:QaTabItem}">                 
                <Border x:Name="ContentBorder"
                Margin="0"
                Background="{DynamicResource AiButtonGreyBrush}"
                BorderBrush="{DynamicResource AiWhiteBrush}"
                BorderThickness="0,.1,0,0">
                    <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
                        <Grid.RowDefinitions>
                            <RowDefinition />
                            <RowDefinition Height="auto" />
                            <RowDefinition />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="33*" />
                            <ColumnDefinition Width="33*" />
                            <ColumnDefinition Width="33*" />
                        </Grid.ColumnDefinitions>
                        <Label 
                            Grid.Row="0" 
                            Grid.Column="3" 
                            VerticalAlignment="Top" 
                            HorizontalAlignment="Right" 
                            Foreground="{DynamicResource AiGreyBrush}" 
                            FontFamily="Segoe UI"
                            Content="{TemplateBinding HotKey}" />
                        <StackPanel 
                            Grid.Row="1" 
                            Grid.Column="0" 
                            Grid.ColumnSpan="2" 
                            Orientation="Horizontal" 
                            HorizontalAlignment="Center">
                            <Image  
                                Grid.RowSpan="2" 
                                Grid.Column="0" 
                                Stretch="Uniform" 
                                Width="25" 
                                HorizontalAlignment="Left" 
                                Source="{TemplateBinding TabImage}" />
                            <TextBlock 
                                TextWrapping="Wrap" 
                                Margin="20,0,0,0" 
                                Width="75" 
                                Foreground="{DynamicResource AiWhiteBrush}" 
                                FontSize="14"
                                Text="{TemplateBinding Title}" />
                        </StackPanel>
                        <Label 
                            Grid.Row="2" 
                            Content="{TemplateBinding Caption}" 
                            Grid.Column="0" 
                            Grid.ColumnSpan="2" 
                            VerticalAlignment="Top" 
                            FontSize="10" 
                            FontFamily="Segoe UI" 
                            FontWeight="Bold" 
                            Foreground="{DynamicResource AiGreyBrush}" />
                        <Image 
                            x:Name="ArrowImage" 
                            Grid.Row="1" 
                            Grid.Column="2" 
                            Source="{DynamicResource TabItemHeaderArrowIcon}" 
                            HorizontalAlignment="Right" 
                            VerticalAlignment="Center" 
                            Width="20" 
                            Height="20" />
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

当我尝试创建此控件的实例时,为什么OnApplyTemplate中的arrowImage为null?

编辑:我之前没有提到我将此控件用作其他控件的基类。当我去使用它时,我将WPF UserControl添加到我的项目中,并将其基类从UserControl更改为QaTabItem。我实际上没有尝试过运行代码,因为设计师正在发生故障。

编辑2:糟糕。在我班上忘了我的依赖属性。

1 个答案:

答案 0 :(得分:2)

德鲁,

不幸的是,如果您使用的setter是密封的,则无法以编程方式在模板或样式中使用FindName。

来自MSDN https://msdn.microsoft.com/en-uS/office/office365/windows.ui.xaml.setter.property.aspx

如果您使用代码访问Setter实例,则如果父样式上的IsSealed属性值为true,则无法更改Setter实例的任何属性的值。单个Setter上的IsSealed属性也会报告此情况。当运行时将样式应用于UI元素并在UI中显示它们时,系统会将这些属性设置为true。尝试更改密封的Setter会引发运行时错误。

然而,一切都不会丢失。我注意到,在您的模板中,控件ArrowImage的来源为DynamicResource。您是否考虑过在代码中将资源设置为App Resource并进行操作的可能性?

要在代码中设置为App Resource,请将以下行添加到App.xaml.cs文件构造函数

App.Current.Resources.Add("TabItemHeaderArrowIcon",null); // <-- Could replace null with a proper image source

然后在您的代码中,您可以按如下方式引用App Resource,

App.Current.Resources["TabItemHeaderArrowIcon"] = your image source

在应用程序关闭时,请确保使用

清理应用程序资源(因为它在内存中分配)
App.Current.Resources.Remove("TabItemHeaderArrowIcon")

这是一种过去对我有用的方法。希望它也能帮到你。

相关问题