MEF:如何在离开视图时禁用重新评估绑定

时间:2016-12-16 10:46:20

标签: wpf binding mef region

我在MEF应用程序中遇到了一个有趣的情况。主工作区是在ContentControl上注册的区域,一次只有一个活动视图。设置和导航工作正常。现在我观察到的是,当我更改此 MainRegion 上的视图时,我再次评估了对viewmodel的所有绑定。

为了检查这个,我在我的视图模型上添加了一个计数器,以查看它的加载频率。当我改变视图A - >查看B - >查看A,然后计数器将是3:

  • 进入View A
  • 离开View A
  • 进入View A

我正在使用普通电话激活某个地区:

region.Activate(view);

调试此问题时,我看到在激活区域时,旧区域被取消激活,最终设置

ContentControl.Content = null;

这似乎修改了可视化树并重新评估旧视图上的所有绑定。

它似乎是MEF和WPF问题的混合体。有没有办法阻止在激活新区域时评估绑定,或者在WPF端阻止在ContentControl.Content变为null时重新评估绑定?

我发现了一个类似的问题,但没有回答: WPF: disable bindings update on detach

1 个答案:

答案 0 :(得分:1)

此问题似乎是ContentControl本身的问题,请参阅此帖子以获取更多信息:http://blogs.microsoft.co.il/tomershamam/2009/09/11/wpf-performance-sweets-contentcontrolcontent-null/

要避免在区域中的视图之间切换时出现性能问题,可以使用该区域的另一个控件将视图保留在可视树中。用修改后的ContentControl替换ItemsControl。我在这篇文章中找到了一个解决方案:https://vslepakov.blogspot.de/2014/09/navigate-faster-with-prism-and-wpf.html。它可以隐藏旧视图并显示新视图。

我修改了这个例子:

public class RegionItemsControl : ItemsControl
{
   protected override bool IsItemItsOwnContainerOverride(object item)
   {
      return false;
   }

   protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
   {
      base.PrepareContainerForItemOverride(element, item);
      ((ContentPresenter)element).ContentTemplate = ItemTemplate;
   }
}

将其添加到您的shell并将其标记为区域:

    <controls:RegionItemsControl 
       prism:RegionManager.RegionName="MainRegion">
       <controls:RegionItemsControl.ItemsPanel>
           <ItemsPanelTemplate>
               <Grid />
           </ItemsPanelTemplate>
       </controls:RegionItemsControl.ItemsPanel>
       <controls:RegionItemsControl.ItemTemplate>
           <DataTemplate>
               <ContentControl Content="{Binding}"/>
           </DataTemplate>
       </controls:RegionItemsControl.ItemTemplate>
   </controls:RegionItemsControl>

导航由事件处理,触发以下代码:

private FrameworkElement _lastView = null;

private bool LoadAndActivateWorkspaceAreaView(Type requestedViewType, IRegion region)
{
    var viewToActivate = region.Views.FirstOrDefault(viewItem => viewItem.GetType() == requestedViewType) as FrameworkElement;
    if (viewToActivate == null)
    {
        viewToActivate = MefContainer.GetExportedValue(requestedViewType) as FrameworkElement;
        if (viewToActivate == null)
            throw new InvalidOperationException("view not found!");

        viewToActivate.Visibility = Visibility.Collapsed;

        region.Add(viewToActivate); // Adds new view to RegionItemsControl
    }

    if (_lastView != null)
        _lastView.Visibility = Visibility.Collapsed;

    _lastView = viewToActivate;
    _lastView.Visibility = Visibility.Visible;
}

此解决方案的一个问题是,在向区域添加新视图时,会重新评估存储在RegionItemsControl中的“旧”视图的绑定。这似乎是我认为ItemsControl的一个问题。