简体   繁体   English

MVVM-从ViewModel访问View中的xaml元素

[英]MVVM - Access xaml element in View from ViewModel

Models: 楷模:

  • TabModel.cs TabModel.cs

  • DisplayTabViewModel.cs - contains few overwritten properties from TabModel like Name, Title etc. DisplayTabViewModel.cs-包含一些来自TabModel的覆盖属性,例如Name,Title等。

ViewModels: ViewModels:

  • MainViewModel.cs MainViewModel.cs

Views: 观看次数:

  • MainWindow.xaml - Window MainWindow.xaml-窗口

  • DisplayTabView.xaml - Usercontrol DisplayTabView.xaml-用户控件


This is pure MVVM pattern, without code-behind. 这是纯MVVM模式,没有代码隐藏。 TabModel invokes EventHandler - RefreshRequested after a Word Document is closed. 在Word文档关闭后, TabModel调用EventHandler- RefreshRequested MainViewModel contains the subscriber. MainViewModel包含订阅者。 Method Refresh() in MainViewModel works fine. MainViewModel中的方法Refresh() 可以正常工作。 The method is triggered after I close the document. 关闭文档后触发该方法。 Now I would like to refresh the WebBrowser in DisplayTabView.xaml from MainViewModel . 现在,我想从MainViewModel刷新DisplayTabView.xaml中WebBrowser I'm struggling with this too many hours already. 我已经为这个小时苦苦挣扎了。 Could you please point me in the right direction. 您能指出我正确的方向吗? Thank you. 谢谢。


TabModel.cs 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 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 DisplayTabView.xaml

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

MainWindow.xaml 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>

The MainViewModel may use an event aggreator or a messenger to send an event/message that any other component, like for example another view model or a view, in your application can subscribe to. MainViewModel可以使用事件聚合器或Messenger来发送事件/消息,您的应用程序中的任何其他组件(例如,其他视图模型或视图)都可以订阅该事件/消息。

By introducing an event aggregator or a messenger in between the publishers and subscribers, you remove the tight coupling between the publisher and the consumer of the event. 通过在发布者和订阅者之间引入事件聚合器或Messenger,可以消除发布者与事件使用者之间的紧密耦合。 Both the publisher and the consumer know only about an event aggregator but they don't know anything about nor have any references to each other. 发布者和使用者都仅了解事件聚合器,但他们彼此一无所知。 Please refer to the following links for more information about the concept. 请参阅以下链接以获取有关该概念的更多信息。

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

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

Most MVVM libraries out there have their own implementation of this kind of thing. 那里的大多数MVVM库都有自己的实现方式。 In Prism it's called an EventAggreator . Prism中,它称为EventAggreator And in MvvmLight it is called a Messenger . MvvmLight中,它称为Messenger

Here are some code samples on how to use them: 以下是一些有关如何使用它们的代码示例:

https://github.com/PrismLibrary/Prism-Samples-Wpf/tree/master/14-UsingEventAggregator 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/ https://marcominerva.wordpress.com/2014/06/25/how-to-send-string-and-content-messages-with-mvvm-light-messenger/

You could of course also implement your own custom event aggregator if you want to. 当然,如果需要,您也可以实现自己的自定义事件聚合器。

Pretty much all MVVM frameworks implement a Message Bus you can use to send messages between View Models, in your case from MainViewModel to DisplayTabViewModel. 几乎所有的MVVM框架都实现了一条消息总线,您可以使用它在View模型之间发送消息,在这种情况下,是从MainViewModel到DisplayTabViewModel。

If you are for some reason against using an MVVM framework you'll have to implement the Message Bus of your own which wouldn't make much sense since there are so many great MVVM frameworks out there... 如果出于某种原因而反对使用MVVM框架,则必须实现自己的消息总线,这没有多大意义,因为那里有很多很棒的MVVM框架...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM