Update viewmodel based on MainWindow event

别说谁变了你拦得住时间么 提交于 2019-12-02 04:18:37

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

I'd go for something like this:

  • 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

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

EDIT: example:

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 );
        }
    }
}

and then register the service

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

in your bootstrapper or your module's initialization.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!