WPF+Prism中如何绑定InteractionRequest弹窗的Window属性至内部控件?
这个问题我之前也碰到过,核心原因是可视化树加载的时序问题:当你的PopupView在XAML中初始化时,它还没有被添加到Prism自动创建的弹窗Window里,这时候用RelativeSource FindAncestor查找Window自然找不到,导致绑定失败。
不用写后台代码,纯XAML就能解决,而且更符合Prism的设计思路,具体方案如下:
方案1:直接绑定Notification的Title(推荐)
Prism的PopupWindowAction在处理InteractionRequest时,会自动把你传入的Notification对象设置为弹窗Window的DataContext,而你的PopupView作为Window的Content,会自动继承这个DataContext。所以你完全不需要找Window,直接绑定Title即可:
修改PopupView.xaml中的TextBlock绑定:
<TextBlock Name="blk" HorizontalAlignment="Left" Margin="47,105,0,0" TextWrapping="Wrap" Text="{Binding Title}" VerticalAlignment="Top" Height="32" Width="151"/>
这样就能直接获取到你在MainViewModel里设置的"Test Title",而且完全避开了可视化树的时序问题。
方案2:隐藏默认窗口标题栏
如果你想完全去掉默认的Window标题栏,只保留自定义的标题,可以给PopupWindowAction添加WindowStyle设置:
<prism:PopupWindowAction IsModal="True" CenterOverAssociatedObject="True"> <prism:PopupWindowAction.WindowStyle> <Style TargetType="Window"> <Setter Property="WindowStyle" Value="None"/> <!-- 可选:添加边框、背景等样式,让弹窗更美观 --> <Setter Property="BorderThickness" Value="1"/> <Setter Property="BorderBrush" Value="#CCCCCC"/> </Style> </prism:PopupWindowAction.WindowStyle> <prism:PopupWindowAction.WindowContent> <local:PopupView/> </prism:PopupWindowAction.WindowContent> </prism:PopupWindowAction>
这样默认的标题栏就会被隐藏,完全用你PopupView里的TextBlock来展示标题。
为什么之前的RelativeSource绑定失败?
再补充解释一下时序问题:
- 当你触发
ShowPopupRequest.Raise(notification)时,Prism首先会实例化你的PopupView - 然后才会创建Window实例,并把
PopupView设置为Window的Content - 在
PopupView的XAML初始化阶段,它还不属于任何Window的可视化树,所以RelativeSource FindAncestor找不到Window元素,绑定表达式就会报错
而直接绑定DataContext里的Title,是因为Prism会在Window创建完成后,把Notification赋值给Window的DataContext,此时PopupView继承了这个DataContext,绑定就能正常工作。
内容的提问来源于stack exchange,提问作者Pramod B R

