基于 MainWindow 事件更新视图模型 [英] Update viewmodel based on MainWindow event

查看:84
本文介绍了基于 MainWindow 事件更新视图模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 UdpClient,在我的 MainWindow 上触发 DataRecevied 事件:

I have a UdpClient, firing off a DataRecevied event on my MainWindow:

public partial class MainWindow : Window
{
    public static YakUdpClient ClientConnection = new YakUdpClient();
    public ClientData;

    public MainWindow()
    {
        InitializeComponent();
        Loaded += OnLoaded;
    }

    private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
    {
        ClientData = new ClientData();
        ClientConnection.OnDataReceived += ClientConnectionOnDataReceived;
    }

    private void ClientConnectionOnDataReceived(object sender, MessageEventArgs messageEventArgs)
    {
        ClientData.Users = messageEvenArgs.ConnectedUsers;
    }
}

我的 ClientData 和 User 类如下所示:

My ClientData and User classes look as follow:

public class ClientData
{
    public List<User> Users {get;set;)
}

public class User
{
    public string Name {get;set;}
}

在我的 MainWindow 上,我有一个名为 UserListView 的 UserControl,它有一个名为 UserListViewModel

On my MainWindow, I have a UserControl called UserListView which has a ViewModel called UserListViewModel

ViewModel 如下所示:

The ViewModel looks as follow:

public class UserListViewModel: BindableBase
{
    public UserListViewModel()
    {
        //I am sure there are better ways of doing this :(
        Users = new ObservableCollection<User>((MainWindow)Application.Current.MainWindow).ClientData.Users
    });

    private ObservableCollection<User> _users;
    public ObservableCollection<User> Users
    {
        get{ return _users;}
        set { this.SetProperty(ref this._users, value); }
    }
}

我在这里遇到的困难是,当 MainWindow 上的 ClientConnectionOnDataReceived 事件被触发时,我想更新我的 ClientData 类,然后应该以某种方式通知我的 Viewmodel列表已更改,随后更新了我的用户界面.

The difficulty I have here, is when the ClientConnectionOnDataReceived event on the MainWindow gets fired, I would like to update my ClientData class, My Viewmodel should then somehow be notified that the list changed, and subsequently update my UI.

谁能给我一个很好的例子来说明如何在 WPF 中使用 MVVM (Prism) 来实现这一点?

Can anyone give me a solid example of how to achieve this using MVVM (Prism) in WPF?

我是 MVVM 的新手,所以我仍在努力解决这个问题.

I am new to MVVM, so i am still trying to figure this out.

推荐答案

首先,没有明显的理由让主窗口进行订阅.

First of all, there's no obvious reason why the main window should do the subscription.

我会做这样的事情:

  • 创建一个封装订阅的服务(并在其构造函数中订阅)
  • 将其注册为单例
  • 让它实现INotifyPropertyChanged(通知消费者Users的变化)
  • 将服务注入UserListViewModel 并观察Users 属性(请参阅PropertyObserver)
  • 当服务中的Users发生变化时,更新用户列表视图模型中的Users
  • create a service that encapsulates the subscription (and subscribes in its constructor)
  • register that as a singleton
  • have it implement INotifyPropertyChanged (to notify consumers of a change to Users)
  • inject the service into UserListViewModel and observe the Users property (see PropertyObserver)
  • when Users in the service changes, update Users in the user list view model

最重要的是,这里不需要 ObservableCollection :-)

and best of all, no need for ObservableCollection here :-)

示例:

interface IUserService : INotifyPropertyChanged
{
    IReadOnlyCollection<User> Users
    {
        get;
    }
}

class YakUdpService : BindableBase, IUserService
{
    private readonly YakUdpClient _yakUdpClient;
    private IReadOnlyCollection<User> _users;

    public YakUdpService()
    {
        _yakUdpClient = new YakUdpClient();
        _yakUdpClient.OnDataReceived += ( s, e ) => Users = e.ConnectedUsers;
    }

    public IReadOnlyCollection<User> Users
    {
        get
        {
            return _users;
        }
        private set
        {
            SetProperty( ref _users, value );
        }
    }
}

class UserListViewModel : BindableBase
{
    private IReadOnlyCollection<UserViewModel> _users;
    private readonly IUserService _userService;
    private readonly PropertyObserver<IUserService> _userServiceObserver;

    public UserListViewModel( IUserService userService )
    {
        _userService = userService;
        _userServiceObserver = new PropertyObserver<IUserService>( userService );
        _userServiceObserver.RegisterHandler( x => x.Users, () => Users = _userService.Users.Select( x => new UserViewModel( x ) ).ToList() );
        //                                                                                                ^^^ should use factory in real code
    }

    public IReadOnlyCollection<UserViewModel> Users
    {
        get
        {
            return _users;
        }
        private set
        {
            SetProperty( ref _users, value );
        }
    }
}

然后注册服务

Container.RegisterType<IUserService, YakUdpService>( new ContainerControlledLifetimeManager() );

在您的引导程序或模块的初始化中.

in your bootstrapper or your module's initialization.

这篇关于基于 MainWindow 事件更新视图模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆