当前位置: 首页 > news >正文

WPF 的 VisualBrush 只刷新显示的视觉效果,不刷新布局范围

WPF 的 VisualBrush 可以帮助我们在一个控件中显示另一个控件的外观。这是非常妙的功能。

但是本文需要说其中的一个 Bug —— 如果使用 VisualBrush 显示另一个控件的外观,那么只会在其显示效果有改变的时候刷新,而不会在目标布局改变的时候刷新布局。


本文内容

    • 用于复现问题的代码
    • 验证问题
    • 问题?
    • VisualBrush 的其他 Bug

用于复现问题的代码

我们现在做一个可以用于验证此问题的布局。

在一个大的 Grid 容器中有一个 Grid 和一个 Border,这个 Grid 将放一个大面积的 Rectangle 和一个表示内容的 TextBlock;而那个 Border 将完全以 VisualBrush 的形式呈现,呈现的内容是此 Grid 中的全部内容。

可以用于验证此问题的布局

它的完整 XAML 代码如下:

<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>

其后台 C# 代码如下,包含每隔 1 秒钟切换 Rectangle 可见性的代码。

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;
            }
        }
    }
}

验证问题

我们知道,VisualBrush 在默认情况下会将 Visual 中的全部内容拉伸到控件中显示,于是可以预估出两个可能的结果:

  • 如果 Rectangle 可见(VisibilityVisible),那么 Border 中以 VisualBrush 显示的内容将完全和下面重叠(因为大小相同,拉伸后正好重叠)。
  • 如果 Rectangle 不可见(VisibilityCollapsed),那么 Border 中以 VisualBrush 显示的内容将仅有文字且拉伸到整个 Border 范围。

然而实际运行真的是这样子吗?

下面的动图是 Rectangle 初始状态可见时,窗口运行后的结果:

初始状态可见

下面的动图是 Rectangle 初始状态不可见时,窗口运行后的结果:

初始状态不可见

注意到了吗?

只有初始状态才能正确反应我们之前预估出的结果,而无论后面怎么再改变可见性,布局都不会再刷新了。只是——后面 VisualBrush 的内容始终重叠。这意味着 VisualBrush 中目标 Visual 的范围增大之后不会再缩小了。

问题?

这是问题吗?

于是在以下 issue 中跟进此问题:

VisualBrush 的其他 Bug

参见:

  • wpf VisualBrush 已知问题 - 林德熙

我的博客会首发于 https://blog.walterlv.com/,而 CSDN 会从其中精选发布,但是一旦发布了就很少更新。

如果在博客看到有任何不懂的内容,欢迎交流。我搭建了 dotnet 职业技术学院 欢迎大家加入。

知识共享许可协议

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

相关文章:

  • .NET/C# 使用 #if 和 Conditional 特性来按条件编译代码的不同原理和适用场景
  • 使用 Roslyn 分析代码注释,给 TODO 类型的注释添加负责人、截止日期和 issue 链接跟踪
  • 为 NuGet 指定检测的 MSBuild 路径或版本,解决 MSBuild auto-detection: using msbuild version 自动查找路径不合适的问题
  • 解决方案文件 sln 中的项目类型 GUID
  • 两种方法设置 .NET/C# 项目的编译顺序,而不影响项目之间的引用
  • 理解 Visual Studio 解决方案文件格式(.sln)
  • nuget.exe 还原解决方案 NuGet 包的时候出现错误:调用的目标发生了异常。Error parsing the nested project section in solution file
  • 找出 .NET Core SDK 是否使用预览版的全局配置文件在哪里(探索篇)
  • 如何在 Visual Studio 2019 中设置使用 .NET Core SDK 的预览版(全局生效)
  • 使用基于 Roslyn 的 Microsoft.CodeAnalysis.PublicApiAnalyzers 来追踪项目的 API 改动,帮助保持库的 API 兼容性
  • Visual Studio 2019 中使用 .NET Core 预览版 SDK 的全局配置文件在哪里?
  • 推荐几款连字字体,在代码编辑器中启用连字字体(Visual Studio Code)
  • 找回你 C 盘丢失的空间(SpaceSniffer)
  • System.InvalidOperationException:“寄宿 HWND 必须是子窗口。”
  • 通过 AppSwitch 禁用 WPF 内置的触摸让 WPF 程序可以处理 Windows 触摸消息
  • ----------
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • IE9 : DOM Exception: INVALID_CHARACTER_ERR (5)
  • 【Linux系统编程】快速查找errno错误码信息
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • DOM的那些事
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • Java 网络编程(2):UDP 的使用
  • JS笔记四:作用域、变量(函数)提升
  • JWT究竟是什么呢?
  • k8s如何管理Pod
  • laravel 用artisan创建自己的模板
  • Redash本地开发环境搭建
  • session共享问题解决方案
  • Vue实战(四)登录/注册页的实现
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 京东美团研发面经
  • 开源地图数据可视化库——mapnik
  • 扫描识别控件Dynamic Web TWAIN v12.2发布,改进SSL证书
  • 使用Gradle第一次构建Java程序
  • 探索 JS 中的模块化
  • 通过npm或yarn自动生成vue组件
  • Spark2.4.0源码分析之WorldCount 默认shuffling并行度为200(九) ...
  • Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...
  • 积累各种好的链接
  • #14vue3生成表单并跳转到外部地址的方式
  • #etcd#安装时出错
  • (1)Android开发优化---------UI优化
  • (AtCoder Beginner Contest 340) -- F - S = 1 -- 题解
  • (DFS + 剪枝)【洛谷P1731】 [NOI1999] 生日蛋糕
  • (Redis使用系列) Springboot 实现Redis 同数据源动态切换db 八
  • (附源码)计算机毕业设计ssm基于B_S的汽车售后服务管理系统
  • (力扣)循环队列的实现与详解(C语言)
  • (亲测有效)解决windows11无法使用1500000波特率的问题
  • (转)大型网站的系统架构
  • ./indexer: error while loading shared libraries: libmysqlclient.so.18: cannot open shared object fil
  • .NET 动态调用WebService + WSE + UsernameToken
  • [ C++ ] template 模板进阶 (特化,分离编译)
  • [<事务专题>]
  • [20150707]外部表与rowid.txt