如何解决如何将 mdiContainer 子项绑定到 viewModel 属性?
我正在将 CodePlex wpfmdi 容器用于我的 WPF 应用程序。
我需要将 MdiContainer
的孩子绑定到 viewModel 属性。
<mdi:MdiContainer Name="Container" Grid.Row="1" Background="GhostWhite" Children="{Binding Path=Container}"/>
如果我这样做,我会收到此错误:
“System.Windows.Data.Binding”类型的对象无法转换为“System.Collections.ObjectModel.ObservableCollection`1[WPF.MDI.MdiChild]”类型
这就是 Children
中的 MdiContainer
属性的样子:
public ObservableCollection<MdiChild> Children { get; set; }
我做错了什么?
解决方法
Children
属性未作为依赖属性公开,这意味着您无法绑定它。此外,它在 MdiContainer
类型的构造函数中初始化一次,然后将处理程序添加到底层 CollectionChanged
的 ObservableCollection<MdiChild>
事件。它永远不会更新或删除。
因此,尽管 Children
属性具有 setter,但如果您使用它来设置不同的集合,则会破坏控制。这也意味着您不能简单地创建附加属性来公开可绑定的 Children
依赖属性。
除此之外,MdiChild
是一个 Control
,因此它实际上与您的视图模型的目的相矛盾。如果您从视图模型中公开一组用户界面控件,这与 MVVM 模式相冲突。视图模型不应该对视图有任何了解。但是,MDI 控件似乎并不遵循自定义控件的通常 WPF 实践,因此这里没有太多改进空间,不支持数据模板,MdiContainer
是 UserControl
并且有非常有限的依赖属性。
如果您真的想用当前的方法继续使用此控件,您可以:
-
创建自定义附加行为以将您的视图模型集合与
Children
的MdiContainer
集合同步,反之亦然,请参阅 XAML behaviors in WPF。 -
使用
Loaded
事件将Children
集合分配给您的视图模型属性。<mdi:MdiContainer Name="Container" Grid.Row="1" Background="GhostWhite" Loaded="MdiContainer_OnLoaded">
private void MdiContainer_OnLoaded(object sender,RoutedEventArgs e) { var mdiContainer = (MdiContainer)sender; var dataContext = (Main)mdiContainer.DataContext; if (dataContext == null) return; dataContext.Children = mdiContainer.Children; }
-
在
EventTrigger
事件上使用Loaded
和设置Children
集合的自定义触发器操作。这只是不需要代码隐藏的先前方法的不同变体。WPF 包的新 XAML 行为取代了
System.Windows.Interactivity
命名空间中的旧 Blend 行为,已包含此类触发器操作。安装 Microsoft.Xaml.Behaviors.Wpf NuGet 包并使用它:<mdi:MdiContainer Name="Container" Grid.Row="1" Background="GhostWhite"> <behaviors:Interaction.Triggers> <behaviors:EventTrigger EventName="Loaded"> <behaviors:ChangePropertyAction TargetObject="{Binding DataContext,ElementName=Container}" PropertyName="Children" Value="{Binding Children,ElementName=Container}"/> </behaviors:EventTrigger> </behaviors:Interaction.Triggers> </mdi:MdiContainer>
请注意,使用这些方法,您要么同步到您自己的集合,要么直接使用您传递给视图模型的 MdiContainer
的集合。这些只是解决方法。如果您想以干净且符合 MVVM 的方式实现这一点,我认为您需要扩展或修复控件本身,这是相当昂贵且不值得推荐的,因为无论如何它似乎都已死。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。