清除并重新添加MergedDictionaries后刷新模板自定义控件

时间:2014-08-22 11:58:40

标签: c# wpf wpf-controls custom-controls resourcedictionary

情况

我制作了一个custom control MessageBar ,它在资源字典中定义了一种样式。此控件具有dependency property 消息,与名称一样,将包含消息。

public class MessageBar : Control
{
        public static readonly DependencyProperty MessageProperty =
            DependencyProperty.Register("Message", typeof(string), typeof(MessageBar),
                new FrameworkPropertyMetadata(string.Empty, OnMessageChanged));

        static MessageBar()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(MessageBar), new FrameworkPropertyMetadata(typeof(MessageBar)));
        }

        public string Message
        {
            get { return (string)GetValue(MessageProperty); }
            set { SetValue(MessageProperty, value); }
        }

        private static void OnMessageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MessageBar messageBar = (MessageBar)d;

            if (e.NewValue != null && !string.IsNullOrWhiteSpace(e.NewValue.ToString()))
            {
                messageBar.Visibility = Visibility.Visible;

                if (messageBar.textBlock == null)
                    messageBar.textBlock = messageBar.GetChildOfType<TextBlock>();

           // Lots of unnecessary code
            }
}

样式

<Style TargetType="{x:Type controls:MessageBar}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type controls:MessageBar}">
                    <Border Background="LightYellow"
                            BorderBrush="Black"
                            BorderThickness="1,0,1,1"
                            CornerRadius="0,0,10,10">
                        <StackPanel VerticalAlignment="Center"
                                    Orientation="Horizontal"
                                    Margin="10,0,10,0">
                            <!-- Actual text -->
                            <TextBlock Padding="4,2,4,2"
                                       Margin="5,0,0,0"
                                       x:Name="tbText"
                                       Text="{TemplateBinding Message}"
                                       FontSize="16"
                                       FontWeight="ExtraBold" />
                        </StackPanel>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
</Style>

当应用程序启动时,默认样式将加载到merged dictionaries中。用户登录后,merged dictionaries中会加载用户选择的样式(可能与默认样式不同)。通过清除merged dictionaries并将正确的resource dictionaries重新添加到merged dictionaries来重新加载样式。

Application.Current.Resources.MergedDictionaries.Clear();
Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary()
{
    Source = ...
});
// Adding happens a few times.

新样式已正确加载,并且在UI中也可以看到。用户界面更改正确。

问题

问题发生在清除并重新添加合并的词典后,我尝试在TextBlock方法中找到OnMessageChanged类型的子项。

messageBar.textBlock = messageBar.GetChildOfType<TextBlock>();

我100%确定我的GetChildOfType<>()方法没有任何问题。在其他地方使用时,它可以正常工作。

重新添加后执行此操作时,没有MessageBar的子元素。 ChildrenCount为0。

当合并的词典未被清除并重新添加时,会找到类型为TextBlock的子元素。这就是我想要的。

我的猜测是,在清除并重新添加后,MessageBar没有正确引用该样式。因此,模板尚未应用。

我已尝试过的内容

我已尝试覆盖ApplyTemplate()控件的OnStyleChanged()MessageBar方法。但没有任何作用。

问题

如何重新加载样式,以便我(GetChildOfType<TextBlock>()方法)可以找到TextBlockOnMessageChanged方法设置我的消息。

提前致谢!

问候Loetn。

1 个答案:

答案 0 :(得分:0)

Try messageBar.ApplyTemplate() before calling GetChildOfType