【问题标题】:Refresh template custom control after clearing and re-adding MergedDictionaries清除并重新添加 MergedDictionaries 后刷新模板自定义控件
【发布时间】:2014-08-22 11:58:39
【问题描述】:

情况

我制作了一个custom control MessageBar,它的样式在资源字典中定义。这个控件有一个dependency propertyMessage,正如名字所说,它将包含一条消息。

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 中也可见。 UI 正确更改。

问题

在清除并重新添加合并字典后,我尝试在 OnMessageChanged 方法中找到类型为 TextBlock 的子级时出现问题。

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

我 100% 确定我的 GetChildOfType&lt;&gt;() 方法没有问题。在其他地方使用时它可以正常工作。

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

当合并的字典没有被清除并重新添加时,会找到一个TextBlock 类型的子元素。这就是我想要的。

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

我已经尝试过的

我已经尝试过覆盖MessageBar 控件的ApplyTemplate()OnStyleChanged() 方法。但没有任何效果。

问题

如何重新加载样式,以便我(GetChildOfType&lt;TextBlock&gt;() 方法)可以找到TextBlock 以在OnMessageChanged 方法中设置我的消息。

提前致谢!

你好。

【问题讨论】:

  • 在调用 GetChildOfType 之前尝试 messageBar.ApplyTemplate()
  • @ethicallogics 成功了。非常感谢!可以这么简单,我什至没有考虑过......如果你在答案中写下这个,我会接受它。
  • :) 我把它写成答案。

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


【解决方案1】:
Try messageBar.ApplyTemplate() before calling GetChildOfType 

【讨论】:

    猜你喜欢
    • 2014-09-18
    • 2015-05-03
    • 1970-01-01
    • 2010-11-03
    • 1970-01-01
    • 2014-01-01
    • 1970-01-01
    • 2019-02-11
    • 1970-01-01
    相关资源
    最近更新 更多