取消

The VisualBrush of WPF only refresh the visual but not the layout

Now we’ll talk about a behavior of WPF VisualBrush. Maybe it is a bug, but let’s view some details and determine whether it is or not.


The reproduction code

Let’s make a XAML layout to reproduce such an issue.

We have a large Grid which contains an inner Grid and an inner Border. The Grid contains a Rectangle which is as large as the Grid itself and a TextBlock which presents some contents. The Border only shows its background which a VisualBrush of the Grid.

The layout that can reproduce this issue

This is the whole XAML file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<Window x:Class="Walterlv.Demo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Walterlv 的 WindowChrome 示例窗口" Height="450" Width="800"
        WindowStartupLocation="CenterScreen">
    <Grid>
        <Grid x:Name="VisualSource">
            <Rectangle x:Name="VisibleOr" Fill="LightCoral" Visibility="Visible" />
            <TextBlock FontSize="24" TextAlignment="Center" VerticalAlignment="Center">
                <Run Text="I'm walterlv, " />
                <LineBreak />
                <Run Text="I'm reproducing this Visual bug." />
            </TextBlock>
        </Grid>
        <Border>
            <Border.Background>
                <VisualBrush Visual="{Binding Source={x:Reference VisualSource}}" />
            </Border.Background>
        </Border>
    </Grid>
</Window>

This is the code-behind. Notice that it changes the visibility of the Rectangle every 1 second.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
using System.Threading.Tasks;
using System.Windows;

namespace Walterlv.Demo
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Loaded += OnLoaded;
        }

        private async void OnLoaded(object sender, RoutedEventArgs e)
        {
            while (true)
            {
                await Task.Delay(1000);
                VisibleOr.Visibility = Visibility.Collapsed;
                await Task.Delay(1000);
                VisibleOr.Visibility = Visibility.Visible;
            }
        }
    }
}

To verify the issue

We know that the VisualBrush shows and stretch the whole Visual so we can predicate only two results:

  • If the Rectangle is visible with Visibility property Visible, the Border background which contains the VisualBrush will be exactly the same with the Grid.
  • If the Rectangle is invisible with Visibility property Collapsed, the Border background which contains the VisualBrush will stretch the whole content to the Border without any area of the Rectangle.

But it is the real result?

The animation picture below shows the result when the Rectangle is visible as the startup:

Visible at the beginning

The animation picture below shows the result when the Rectangle is invisible as the startup:

Invisible at the beginning

Did you notice that?

Only at the very beginning when the program runs it behaves the same as we predicted. But when we change the visibility of the Rectangle the layout never changes.

The issue?

I’ve fired this issue into GitHub and this is the link:

本文会经常更新,请阅读原文: https://blog.walterlv.com/post/visual-brush-refresh-views-only-but-not-layout-en.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

知识共享许可协议

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 吕毅 (包含链接: https://blog.walterlv.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 ([email protected])

登录 GitHub 账号进行评论