WPF窗口ResizeMode=CanResizeWithGrip时,如何实现ProgressBar随窗口缩放更新宽度
WPF窗口缩放时ProgressBar宽度适配解决方案
一、先修正你现有代码的问题
你的代码目前有三个核心问题:
ProgresbarWidthSetter里新建了MainPage实例,这不是当前运行的窗口实例,根本拿不到正确的MusicBar宽度- 没有监听窗口尺寸变化事件来触发更新逻辑
- 用
ObservableCollection<double>的索引绑定存在缺陷:修改索引元素值不会触发UI更新(ObservableCollection只监听集合的增/删/移动操作,不监听元素本身的修改)
步骤1:给窗口绑定尺寸变化事件
在XAML的Window标签里添加SizeChanged事件:
<Window x:Class="Lista6.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Lista6" mc:Ignorable="d" Title="MainPage" Height="650" Width="1000" Background="#36393F" ResizeMode="CanResizeWithGrip" Icon="/img/Ikonka2.png" WindowStyle="None" SizeChanged="Window_SizeChanged">
步骤2:修正后台更新逻辑
在MainPage.xaml.cs里实现事件处理方法,同时修复ObservableCollection的更新问题:
public partial class MainPage : Window { private AppOperator _vm; public MainPage() { InitializeComponent(); _vm = new AppOperator(); DataContext = _vm; } private void Window_SizeChanged(object sender, SizeChangedEventArgs e) { // 用ActualWidth而非Width,因为自动布局下Width可能为NaN var targetWidth = MusicBar.ActualWidth; // 替换集合元素来触发UI更新(因为ObservableCollection索引修改不通知) _vm.ProgresBarWidth.RemoveAt(0); _vm.ProgresBarWidth.Add(targetWidth); } }
二、更优实现:完全无需后台代码
WPF的声明式绑定可以直接解决这个问题,不用ObservableCollection和事件处理,是更符合WPF设计思想的方案:
直接把ProgressBar的Width绑定到目标Grid的ActualWidth属性:
<ProgressBar Foreground="White" Value="50" BorderThickness="0" Background="Gray" Height="5" Width="{Binding ElementName=MusicBar, Path=ActualWidth}"/>
注意:确保目标Grid的XAML里设置了x:Name="MusicBar",这样ElementName才能找到它。
如果ProgressBar不在目标Grid的直接子层级,可以用RelativeSource向上查找父级Grid:
<ProgressBar Foreground="White" Value="50" BorderThickness="0" Background="Gray" Height="5" Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type Grid}}, Path=ActualWidth}"/>
这种方式会自动跟随Grid的宽度变化更新ProgressBar,完全不需要写任何后台逻辑。
关键说明
ActualWidth是控件渲染后的真实宽度,比Width更可靠,自动布局场景下Width经常是NaN- 如果你一定要用ObservableCollection的方式,必须用实现
INotifyPropertyChanged的包装类来封装double值,或者通过增删元素触发集合变化通知,直接修改索引值不会触发UI更新
内容的提问来源于stack exchange,提问作者Mateusz Rosiński
相关产品推荐
相关产品推荐

