WPF - MVVM Light - Unity - 重新加载当前用户控件时不会触发事件

时间:2017-09-06 18:17:45

标签: c# wpf mvvm mvvm-light service-locator

我有一个有趣的问题,当视图被自身替换时,事件不会被触发。

首先,设置:我正在创建ViewModel和App.xaml资源字典中的View之间的连接:

 <DataTemplate DataType="{x:Type vm:MyViewModel}">
     <v:MyView />
 </DataTemplate>

我有一个应用程序阶段,我使用ServiceLocator创建我的实例:

this.stageViewModel.ActiveStageViewModel = Util.GetInstanceFromDI<MyViewModel>();

在我的舞台上,我使用绑定到ActiveStageViewModel的内容控件将它们全部拉到一起:

<ContentControl Content="{Binding ActiveStageViewModel}" Margin="0" />

所有这一切都很有效,当我导航到MyViewModel时,正确的视图显示并且看起来很好。所有加载和调整大小事件都会正常启动。

但是,如果我第二次尝试导航到MyViewModel,除了DataContextChanged之外,没有任何事件触发。

我使用Observer监视大小更改事件,以便我可以决定一些样式和滚动选项,因此我需要在第二次加载时触发加载事件以刷新观察者中的值。在任何情况下,不在重复的视图加载上触发事件似乎是一种干扰而不是帮助的性能特征。

它正在做的是在渲染内容和渲染内容之间进行比较,如果渲染未更改则不会触发事件。

我尝试了一些事情来强制更新,但没有成功,或者成功打破了我想要的MVVM方法。

我尝试的第一件事是在重置实例之前清空ActiveStageViewModel。这根本不起作用。我的猜测是,因为它永远不会呈现任何东西,所以它永远不会丢弃缓存的View。

我尝试的第二件事是在DataContextChanged事件触发时强制使用FrameworkElement.InvalidateMeasure(),FrameworkElement.InvalidateArrange()和FrameworkElement.InvalidateVisual()。这本身不起作用,大概是因为Cached View比较仍然发生。

最后,工作(但很糟糕)的是将DataContextChanged事件附加到View,然后在事件处理程序内的元素上设置高度。

<DataTemplate DataType="{x:Type vm:MyViewModel}">
    <v:MyView DataContextChanged="FrameworkElement_DataContextChanged" />
</DataTemplate>




private void FrameworkElement_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    DispatcherTimer timer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(10) };
    var el = (FrameworkElement)sender;
    bool addOperation = false;
    double height = el.ActualHeight;
    timer.Tick += (s,ev) =>
    {
        el.Height = addOperation ? height + .001 : height - .001;
        addOperation = !addOperation;
        if (!addOperation)
        {
            timer.Stop();
        }
    };

    timer.Start();
}

这是有效的,因为我有效地强制在DataContextChanged事件中进行布局更改(两次,在20毫秒内,因此对于用户来说是不可观察的),显然使得正在进行的任何视图缓存比较无效上。显然,在View / View Model声明中添加一个eventhandler并不符合MVVM的松散耦合方案。当然,它是在应用程序设置,但仍然看起来很糟糕。

有没有人对这种现象有过任何经验,并且在没有这种暴力破解的情况下强行重新渲染的方法呢?

0 个答案:

没有答案