Prism.WPF:导航时修改MainWindow的Window.Effect实现模糊效果
基于Prism的WPF导航时模糊效果实现方案
一、修复导航前模糊不生效的问题
1. 纠正属性赋值方式
你之前直接给私有字段_fuzzy赋值不会触发UI的属性变更通知,必须通过公开属性的setter(Fuzzy = ef)设置,Prism的SetProperty才会触发PropertyChanged事件,让UI同步更新效果。修改后的模糊设置方法:
private void PerformBlur() { Fuzzy = new BlurEffect { Radius = 4 }; }
2. 确保UI先更新再执行导航
_regionManager.RequestNavigate是异步操作,UI更新模糊效果需要优先占用UI线程处理。可以通过Dispatcher将导航操作延迟到UI队列的后续执行,确保模糊效果先渲染完成:
private async void Navigate(string viewName) { PerformBlur(); // 让UI线程优先处理模糊效果更新 await Application.Current.Dispatcher.InvokeAsync(() => {}); _regionManager.RequestNavigate("ContentRegion", viewName); }
3. 符合MVVM规范的命令绑定
菜单按钮直接绑定ViewModel的DelegateCommand,无需后台代码:
<!-- 导航按钮示例 --> <Button Content="跳转至目标页面" Command="{Binding NavigateCommand}" CommandParameter="TargetViewName" />
ViewModel中初始化命令:
public DelegateCommand<string> NavigateCommand { get; private set; } public MainWindowViewModel(IRegionManager regionManager) { _regionManager = regionManager; NavigateCommand = new DelegateCommand<string>(Navigate); }
二、模糊效果的动画实现
方式1:ViewModel驱动的属性动画(MVVM友好)
在ViewModel中新增控制模糊半径的属性,通过绑定关联到BlurEffect:
private double _blurRadius; public double BlurRadius { get => _blurRadius; set => SetProperty(ref _blurRadius, value); } // 初始化时绑定BlurRadius到BlurEffect的Radius public MainWindowViewModel(IRegionManager regionManager) { _regionManager = regionManager; NavigateCommand = new DelegateCommand<string>(Navigate); var blurEffect = new BlurEffect(); BindingOperations.SetBinding(blurEffect, BlurEffect.RadiusProperty, new Binding(nameof(BlurRadius)) { Source = this }); Fuzzy = blurEffect; }
触发动画的方法:
private void AnimateBlur() { var animation = new DoubleAnimation { From = 0, To = 4, Duration = TimeSpan.FromMilliseconds(300), EasingFunction = new QuadraticEase() // 平滑缓动效果 }; BeginAnimation(nameof(BlurRadius), animation); }
修改导航方法,启动动画并在导航完成后恢复:
private async void Navigate(string viewName) { AnimateBlur(); await Application.Current.Dispatcher.InvokeAsync(() => {}); _regionManager.RequestNavigate("ContentRegion", viewName, result => { // 导航完成后执行模糊消失动画 var resetAnimation = new DoubleAnimation(0, TimeSpan.FromMilliseconds(300)); BeginAnimation(nameof(BlurRadius), resetAnimation); }); }
方式2:纯XAML的Storyboard动画(解耦UI逻辑)
在MainWindow的资源中定义动画:
<Window.Resources> <QuadraticEase x:Key="QuadraticEase"/> <Storyboard x:Key="BlurInAnimation"> <DoubleAnimation Storyboard.TargetProperty="(Effect).(BlurEffect.Radius)" From="0" To="4" Duration="0:0:0.3" EasingFunction="{StaticResource QuadraticEase}"/> </Storyboard> <Storyboard x:Key="BlurOutAnimation"> <DoubleAnimation Storyboard.TargetProperty="(Effect).(BlurEffect.Radius)" To="0" Duration="0:0:0.3" EasingFunction="{StaticResource QuadraticEase}"/> </Storyboard> </Window.Resources>
通过DataTrigger绑定ViewModel的导航状态标志:
<Window.Style> <Style TargetType="Window"> <Style.Triggers> <DataTrigger Binding="{Binding IsNavigating}" Value="True"> <DataTrigger.EnterActions> <BeginStoryboard Storyboard="{StaticResource BlurInAnimation}"/> </DataTrigger.EnterActions> <DataTrigger.ExitActions> <BeginStoryboard Storyboard="{StaticResource BlurOutAnimation}"/> </DataTrigger.ExitActions> </DataTrigger> </Style.Triggers> </Style> </Window.Style>
ViewModel中新增导航状态属性:
private bool _isNavigating; public bool IsNavigating { get => _isNavigating; set => SetProperty(ref _isNavigating, value); }
修改导航方法控制状态:
private async void Navigate(string viewName) { IsNavigating = true; await Application.Current.Dispatcher.InvokeAsync(() => {}); _regionManager.RequestNavigate("ContentRegion", viewName, result => { IsNavigating = false; }); }
内容的提问来源于stack exchange,提问作者Tim Jones
相关产品推荐
相关产品推荐

