[英]How to bind mdiContainer children to viewModel property?
我正在为我的 WPF 应用程序使用 CodePlex wpfmdi 容器。
我需要将MdiContainer
的孩子绑定到 viewModel 属性。
<mdi:MdiContainer Name="Container" Grid.Row="1" Background="GhostWhite" Children="{Binding Path=Container}"/>
如果我这样做,我会收到此错误:
'System.Windows.Data.Binding' 类型的 Object 无法转换为'System.Collections.ObjectModel.ObservableMFChild'1 类型
这是MdiContainer
中的Children
属性的样子:
public ObservableCollection<MdiChild> Children { get; set; }
我究竟做错了什么?
Children
属性不作为依赖属性公开,这意味着您无法绑定它。 此外,它在MdiContainer
类型的构造函数中初始化一次,然后将处理程序添加到底层ObservableCollection<MdiChild>
的CollectionChanged
事件。 它永远不会更新或删除。
因此,虽然Children
属性有一个 setter,但如果您使用它来设置不同的集合,它将破坏控件。 这也意味着您不能简单地创建附加属性来公开可绑定的Children
依赖项属性。
除此之外, MdiChild
是一个Control
,因此它实际上与您查看 model 的目的相矛盾。 如果您从视图 model 公开一组用户界面控件,则这与 MVVM 模式冲突。 视图模型不应该对视图有任何了解。 但是,MDI 控件似乎没有遵循自定义控件通常的 WPF 做法,因此这里没有太大的改进空间,不支持数据模板, MdiContainer
是一个UserControl
,依赖属性非常有限。
如果您真的想继续使用当前方法使用此控件,您可以:
创建自定义附加行为以将您的视图 model 集合与MdiContainer
的Children
集合同步,反之亦然,请参阅WPF 中的 XAML 行为。
使用Loaded
事件将Children
集合分配给您的视图 model 属性。
<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; }
对Loaded
事件使用EventTrigger
,并使用设置Children
集合的自定义触发器操作。 这只是先前方法的不同变体,不需要代码隐藏。
The new XAML behaviors for WPF package, which replaces the legacy Blend behaviors from the System.Windows.Interactivity
namespace already includes such a trigger action. 安装Microsoft.Xaml.Behaviors.Wpf NuGet ZEFE90A8E604A77640E8ZD03 和使用这个:
<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>
请注意,使用这些方法,您可以同步到自己的集合,也可以直接使用传递给视图 model 的MdiContainer
的集合。 这些只是解决方法。 如果您想以干净且符合 MVVM 的方式实现此功能,我认为您需要扩展或修复控件本身,这是相当昂贵且不推荐的,因为它似乎已经死了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.