基于 MainWindow 事件更新视图模型 [英] Update viewmodel based on MainWindow event
问题描述
我有一个 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 toUsers
) - inject the service into
UserListViewModel
and observe theUsers
property (see PropertyObserver) - when
Users
in the service changes, updateUsers
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屋!