WPF 如何确定需要重新绘制的内容?我该如何查找?

3

嗯,这涉及到WPF的基础知识:

简单来说,如何实现自己的RenderThread。

我正在解决一个问题,需要在WPF应用程序中使用10Bit显示。出于这个和其他原因,必须使用OpenGL(它非常适合进行10Bit操作)。绑定和WPF控件被广泛使用并受到我们的喜爱。因此,在少数控件中,我希望在我的OpenGL上下文中使用它们,甚至可能绘制它们。

有趣的是,我使用自己的PresentationSource将一些WPF部分作为独立的对象树工作。布局工作正常,但由于缺少某些部分(焦点),事件目前失败。可能事件从未起作用,因为不可能从一些内部类(如CompositionTarget)派生...:-/

但是:

因此,我可以在我的OpenGL上下文中进行自己的绘图(只是几个按钮和边框),但我无法从脑海中挥之不去的想法中走出来,检查WPF Visual-Tree,抓取所有的DrawingGroups,并在OpenGL中重新绘制。

我得到的是一棵DrawingGroupsEllipseGeometryRectangleGeometry的树-因此是可绘制的基本几何图形。

    DrawingGroup drawing = VisualTreeHelper.GetDrawing((Visual) firstChild);

那个想法的问题在于:我如何确定/检查我的可视树是否发生了变化。我指的不是整个可视树,而是其中的一个依赖属性。具体来说,WPF提供了一个重写方法protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved),但据我观察,它并没有被频繁调用。我想要观察的是:当动画发生时,例如对可视树中的Width、Opacity或Brushes进行动画处理时,我需要重新绘制我的OpenGL上下文。那么WPF是如何确定这一点的,我该如何观察到呢?

只是我的观点,但是看起来你在这里使用了错误的工具。 - Robinson
1个回答

2

我认为LayoutUpdated可以提供您所需的功能。

请考虑以下代码示例: XAML:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Width="525" Loaded="MainWindow_OnLoaded">
    <StackPanel>
        <Canvas x:Name="TargetCanvas"  Height="300">
            <Rectangle x:Name="Subject" Canvas.Top="50" Canvas.Left="50" Fill="Maroon" Height="25" Width="25"/>
        </Canvas>
        <Button Content="Move">
            <Button.Triggers>
                <EventTrigger RoutedEvent="Button.Click">
                    <BeginStoryboard>
                        <Storyboard Target="{Binding ElementName=Subject}" TargetProperty="(Canvas.Left)" AutoReverse="True">
                            <DoubleAnimation To="200" Duration="00:00:02"/>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Button.Triggers>
        </Button>
    </StackPanel>
</Window>

并且代码后台:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
    {
        TargetCanvas.LayoutUpdated += TargetCanvas_LayoutUpdated;
    }

    void TargetCanvas_LayoutUpdated(object sender, EventArgs e)
    {
        Debug.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff") + ": Layout updated\n");
    }
}

针对RenderTransform(如TranslateTransform)的动画不会影响布局,因此不会触发LayoutUpdated事件。 - Kevin Gosse
确实,当我尝试添加RenderTransform时,我确实得到了一些结果(尽管诚实地说,它们没有没有变换的效果好)。但是他谈到了不需要变换即可进行动画处理的不透明度和画刷。 - CKII
你们两个都是对的。首先感谢你们。该事件在布局更改时触发,但其他重要更改(如颜色等)不会触发。所以我在考虑是否应该将其标记为答案...... - Robetto

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