根据MainWindow事件更新viewmodel

时间:2016-08-12 10:08:12

标签: wpf prism viewmodel

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

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类如下所示:

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

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

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

ViewModel如下所示:

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类,然后应该以某种方式通知My Viewmodel列表已更改,并且随后更新我的用户界面。

有没有人能给我一个如何在WPF中使用MVVM(Prism)实现这个目的的实例?

我是MVVM的新手,所以我仍然想要解决这个问题。

1 个答案:

答案 0 :(得分:5)

首先,没有明显的理由说明主窗口应该进行订阅。

我会选择这样的事情:

  • 创建一个封装订阅的服务(并在其构造函数中订阅)
  • 将其注册为单身人士
  • 让它实施INotifyPropertyChanged(通知消费者对Users的更改)
  • 将服务注入UserListViewModel并观察Users属性(请参阅PropertyObserver
  • 当服务中的Users发生更改时,请在用户列表视图模型中更新Users

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

编辑:示例:

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

在你的引导程序或模块的初始化中。