如何冻结所有freezable WPF对象?

时间:2016-05-06 08:30:46

标签: c# wpf performance freeze

我想冻结窗口中的所有freezable对象。(以获得更好的性能)

要做到这一点,我使用了几个这样的循环:

    foreach (Brush item in FindLogicalChildren<Brush>(myWin))
                  if( item != null && item.CanFreeze)item.Freeze();

    foreach (Transform item in FindLogicalChildren<Transform>(myWin))
                   if( item != null && item.CanFreeze)item.Freeze();

    foreach (Geometry item in FindLogicalChildren<Geometry>(myWin))
                   if( item != null && item.CanFreeze)item.Freeze();

但它不起作用。

如何在任何可冻结的WPF对象上调用Freeze()

编辑:

我刚刚意识到FindLogicalChildren找不到任何东西,所以它不起作用。

EDIT2:

如何使用ONE循环在任何freezable对象上调用Freeze()。

请帮帮我。

2 个答案:

答案 0 :(得分:4)

你是对的,如果一切都被冻结,性能会得到真正的提升。

您可以在XAML中执行此操作。

在所有资源字典中,添加ice命名空间:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:ice="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options">

然后,对于每个可冻结的XAML元素,将其冻结。例子:

<SolidColorBrush ice:Freeze="True" x:Key="GlyphDisabledFillBrush" Color="{StaticResource Color_005}"/>
<LinearGradientBrush ice:Freeze="True" x:Key="PendingOrderPositiveBrush"  EndPoint="8,8" StartPoint="0,0" SpreadMethod="Repeat"  MappingMode="Absolute">
    <GradientStop ice:Freeze="True" Color="{StaticResource PendingOrderLightPositiveColor}" Offset="0"/>
    <GradientStop ice:Freeze="True" Color="{StaticResource PendingOrderLightPositiveColor}" Offset="0.44"/>
    <GradientStop ice:Freeze="True" Color="{StaticResource PendingOrderDarkPositiveColor}" Offset="0.44"/>
    <GradientStop ice:Freeze="True" Color="{StaticResource PendingOrderDarkPositiveColor}" Offset="0.6"/>
    <GradientStop ice:Freeze="True" Color="{StaticResource PendingOrderLightPositiveColor}" Offset="0.6"/>
    <GradientStop ice:Freeze="True" Color="{StaticResource PendingOrderLightPositiveColor}" Offset="1"/>
</LinearGradientBrush>

不冻结元素的好处

使用非冻结画笔的唯一好处是我们可以在运行时更改主题。如果我们不担心主题变化,那么我们可以通过冻结所有画笔来获得良好的性能提升。冻结元素也是我们可以使用单独的调度程序支持多线程窗口的唯一方法。

答案 1 :(得分:0)

我会使用以下内容(感谢that回答):

public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
    if (depObj != null)
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
            if (child != null && child is T)
            {
                yield return (T)child;
            }

            foreach (T childOfChild in FindVisualChildren<T>(child))
            {
                yield return childOfChild;
            }
        }
    }
}

foreach (Freezable item in FindVisualChildren<Freezable>(myWin))
              if( item != null && item.CanFreeze)item.Freeze();

(我无法在这里测试我的代码)