如何将mdiconcontainer的孩子绑定到viewModel属性?



我的WPF应用程序使用CodePlex wpfmdi容器。

我需要将MdiContainer的子节点绑定到viewModel属性。

<mdi:MdiContainer Name="Container" Grid.Row="1" Background="GhostWhite" Children="{Binding Path=Container}"/>

如果我这样做,我得到这个错误:

类型为"System.Windows.Data"的对象。绑定'不能转换为类型'System.Collections.ObjectModel.ObservableCollection ' 1[WPF.MDI.MdiChild]'

MdiContainer中的Children属性是这样的:

public ObservableCollection<MdiChild> Children { get; set; }

我做错了什么?

Children属性没有作为依赖属性公开,这意味着您不能绑定它。此外,它在MdiContainer类型的构造函数中初始化一次,然后将处理程序添加到底层ObservableCollection<MdiChild>CollectionChanged事件中。它永远不会更新或删除。

因此,尽管Children属性有一个setter,但如果使用它来设置不同的集合,它将破坏控制。这也意味着您不能简单地创建附加属性来公开可绑定的Children依赖属性。

除此之外,MdiChildControl,因此它实际上与视图模型的目的相矛盾。如果从视图模型公开一组用户界面控件,则会与MVVM模式发生冲突。视图模型不应该有任何关于视图的知识。然而,MDI控件似乎没有遵循自定义控件的通常WPF实践,因此这里没有太多的改进空间,不支持数据模板,MdiContainerUserControl,并且依赖属性非常有限。

如果您真的想继续使用当前的方法来处理这个控件,您可以:

  • 创建一个自定义附加行为来同步您的视图模型集合与MdiContainerChildren集合,反之亦然,参见WPF中的XAML行为。

  • 使用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;
    }
    
  • Loaded事件上使用EventTrigger,通过自定义触发动作设置Children集合。这只是前一种方法的不同变体,不需要代码隐藏。

    WPF包的新XAML行为取代了System.Windows.Interactivity命名空间中遗留的Blend行为,它已经包含了这样一个触发器动作。安装Microsoft.Xaml.Behaviors。WpfNuGet包并使用:

    <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兼容的方式实现这一点,我认为你需要扩展或修复控件本身,这是相当昂贵的,不推荐,因为它似乎已经死了。

相关内容

  • 没有找到相关文章

最新更新