MVVM - 从ViewModel

时间:2018-05-07 15:44:37

标签: c# wpf xaml mvvm

型号:

  • TabModel.cs

  • DisplayTabViewModel.cs - 包含来自TabModel的少量覆盖属性,如名称,标题等。

的ViewModels:

  • MainViewModel.cs

查看:

  • MainWindow.xaml - Window

  • DisplayTabView.xaml - Usercontrol

这是纯MVVM模式,没有代码隐藏。 Word文档关闭后, TabModel 会调用EventHandler - RefreshRequested MainViewModel 包含订阅者。 MainViewModel 中的方法刷新()工作正常。关闭文档后触发该方法。现在,我想从 MainViewModel 中刷新 DisplayTabView.xaml 中的 WebBrowser 。我已经在这太多时间里苦苦挣扎了。你能指点我正确的方向吗?谢谢。

TabModel.cs

public abstract class TabModel : ITabModel, INotifyPropertyChanged
{
    public async void HiddenFileExists()
    {
        (...)

        OnRefreshRequested();
    }

    public delegate void RefreshRequestedEventHandler(object source, EventArgs args);

    public event RefreshRequestedEventHandler RefreshRequested;

    public virtual void OnRefreshRequested()
    {
        RefreshRequested?.Invoke(this, EventArgs.Empty);
    }
}

MainViewModel.cs

public class MainViewModel : INotifyPropertyChanged
{
    private readonly ObservableCollection<ITabModel> tabs;

    private void DisplayFileTab(object parameter)
    {
        (...)

        tabs.ElementAt(TabIndex).RefreshRequested += Refresh;
    }

    public void Refresh(object source, EventArgs args)
    {
        MessageBox.Show("Refresh");
    }

DisplayTabView.xaml

<Grid>
    <WebBrowser h:WebBrowserExtensions.BindableSource="{Binding FileUrl}" Tag="{Binding AcceptedKeywordsArray}" h:WebBrowserExtensions.BindableLoaded="{Binding}" />
</Grid>

MainWindow.xaml

<Grid>
    <DockPanel>
        <TabControl Name="tabControl" ItemsSource="{Binding Tabs}" SelectedIndex="{Binding TabIndex}">
            <TabControl.Resources>
                <DataTemplate DataType="{x:Type m:DisplayTabViewModel}">
                    <v:DisplayTabView x:Name="DisplayTab"/>
                </DataTemplate>
            </TabControl.Resources>
            <TabControl.ItemTemplate>
                <DataTemplate DataType="{x:Type m:ITabModel}">
                    <Grid>
                        (...)
                    </Grid>
                </DataTemplate>
            </TabControl.ItemTemplate>
        </TabControl>
    </DockPanel>
</Grid>

2 个答案:

答案 0 :(得分:2)

MainViewModel可以使用事件扩展器或信使来发送事件/消息,使您的应用程序中的任何其他组件(例如另一个视图模型或视图)可以订阅。

通过在发布者和订阅者之间引入事件聚合器或信使,可以消除发布者与事件使用者之间的紧密联系。发布者和消费者都只知道事件聚合器,但他们不知道任何事情,也没有任何相互引用。有关该概念的更多信息,请参阅以下链接。

使用事件聚合器模式在视图模型之间进行通信: https://blog.magnusmontin.net/2014/02/28/using-the-event-aggregator-pattern-to-communicate-between-view-models/

MVVM - MVVM中的Messenger和View Services: https://msdn.microsoft.com/en-us/magazine/jj694937.aspx

大多数MVVM库都有自己的这种实现方式。在Prism中,它被称为EventAggreator。在MvvmLight中,它被称为Messenger

以下是一些有关如何使用它们的代码示例:

https://github.com/PrismLibrary/Prism-Samples-Wpf/tree/master/14-UsingEventAggregator

https://marcominerva.wordpress.com/2014/06/25/how-to-send-string-and-content-messages-with-mvvm-light-messenger/

如果您愿意,您当然也可以实现自己的自定义事件聚合器。

答案 1 :(得分:0)

几乎所有的MVVM框架都实现了一个消息总线,您可以使用它在View Models之间发送消息,在您的情况下从MainViewModel发送到DisplayTabViewModel。

如果你出于某种原因反对使用MVVM框架,你将不得不实现自己的消息总线,因为那里有很多优秀的MVVM框架,所以没有多大意义......