WPF:资源更改时是否触发事件?

6
有没有一种方法可以在特定的 WPF 资源值改变时得到通知?
我们需要在一个 WPF 应用程序中动态地适应内容字体大小... 对于 WPF 控件,我们将 Control.FontSize 设置为动态资源,字体会自动调整大小。不幸的是,我们还有一个嵌入的 winforms 控件,字体大小无法通过这种方式设置。想法是订阅每个资源值更改时触发的事件,并实现自定义的 winforms 控件刷新。有什么建议吗?
提前感谢您!

你看过这个网址吗:https://dev59.com/93VD5IYBdhLWcg3wGHeu? - Josh
Code-behind可以帮助声明公共事件。但是什么时候应该触发此事件?在WPF框架中是否有任何事件告诉我们资源已更改? - jeromerg
1
我在 .Net 源代码中找到了 FrameworkElement.ResourcesChanged 事件,但它是完全 internal 的。无法将一些处理程序挂钩到此事件...有什么建议吗?我认为唯一剩下的方法是将动态资源设置为专用依赖属性(使用 Prop={DynamicResource MyResource}),并使用依赖属性来触发更改事件。 - jeromerg
2个回答

7

所以,在考虑了所有可能的方法后,我引入了一种新的行为,它在特定的 WPF 资源每次更改时触发一个事件。

可以从https://github.com/jeromerg/ResourceChangeEvent下载或克隆源代码。

public class ResourceChangeNotifierBehavior 
  : System.Windows.Interactivity.Behavior<FrameworkElement>
{
    public static readonly DependencyProperty ResourceProperty 
            = DependencyProperty.Register("Resource", 
                   typeof(object),
                   typeof(ResourceChangeNotifierBehavior),
                   new PropertyMetadata(default(object), ResourceChangedCallback));

    public event EventHandler ResourceChanged;

    public object Resource
    {
        get { return GetValue(ResourceProperty); }
        set { SetValue(ResourceProperty, value); }
    }

    private static void ResourceChangedCallback(DependencyObject dependencyObject,
                                                DependencyPropertyChangedEventArgs args)
    {
        var resourceChangeNotifier = dependencyObject as ResourceChangeNotifierBehavior;
        if (resourceChangeNotifier == null)
            return;

        resourceChangeNotifier.OnResourceChanged();
    }

    private void OnResourceChanged()
    {
        EventHandler handler = ResourceChanged;
        if (handler != null) handler(this, EventArgs.Empty);
    }
}

为了能够在XAML文件中挂接事件处理程序OnResourceChanged,可以采用以下方式:

<i:Interaction.Behaviors>
    <Behaviours:ResourceChangeNotifierBehavior 
                Resource="{DynamicResource MyDynamicResourceKey}"
                ResourceChanged="OnResourceChanged"/>
</i:Interaction.Behaviors>

希望能对您有所帮助...


0
我曾经遇到过同样的问题,但实际上我想在任何资源更改时得到通知。在我的情况下,某些DependencyObject上使用了DynamicResource,而这些对象不在可视树中。因此,如果资源更改,则属性不会自动更新。
使用jeromerg发现的内部事件,我编写了一个小扩展方法来注册ResourceChanged事件:
public static void NotifyOnResourcesChanged(this FrameworkElement element, EventHandler onResourcesChanged)
{
    ResourcesChangedEvent.AddMethod.Invoke(element, new object[] { onResourcesChanged });
}
private static readonly EventInfo ResourcesChangedEvent = typeof(FrameworkElement).GetEvent("ResourcesChanged", BindingFlags.Instance | BindingFlags.NonPublic);

在我的事件处理程序中,我通过InvalidateProperty通知目标属性进行强制更新。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接