视图模型中的计时器
我在外部程序集中有服务类,我使用 MEF 将此类注入到视图模型类中。我需要从视图模型中每 3-4 秒调用一次服务方法。
我从服务中获取新数据作为字典。该字典绑定到视图中的列表框。我需要刷新视图中的数据列表框。
在我的解决方案中,我使用 DispatcherTimer,但我是 calibur.micto 以及 MVVM 和 WPF 的绝对初学者。我不知道什么是适合我的情况的解决方案。因此,如果有人有预付款,我将不胜感激。
我的解决方案在这里:
[Export("MainScreen", typeof(IMainViewModel))]
public class MainViewModel : Screen, IMainViewModel
{
[Import]
private Service _service;//import with MEF from external assembly
[Import]
private Connection _conn;//import with MEF from external assembly
//this dictionary is bind to the listbox in view
private MyObservableDictionary<string, User> _users = null;
//temp dictionry
private MyObservableDictionary<string, User> _freshUsers = null;
private int _selectedUserIndex;
private DispatcherTimer _dispatcherTimer;
public Account Account{ get; set;}
public int SelectedUsersIndex
{
get { return _selectedUserIndex; }
set
{
_selectedUserIndex = value;
NotifyOfPropertyChange("SelectedUsersIndex");
}
}
public MainViewModel()
{
_dispatcherTimer = new DispatcherTimer();
_dispatcherTimer.Tick += DispatcherTimer_Tick;
_dispatcherTimer.Interval = TimeSpan.FromSeconds(3);
_dispatcherTimer.Start();
}
//I get every 3-4 sec from server new JSON data and I need update with this data listbox in view
private void DispatcherTimer_Tick(object sender, EventArgs eventArgs)
{
//server ping, call service method
Account.Ping = _service.Ping(Account);
//Refresh data in dictionary
_freshUsers = _service.LoadUsers(Account);
_users.Clear();
SelectedUsersIndex = 1;
foreach (var freshUser in _freshUsers)
{
_users.Add(freshUser);
}
//check if you have new messanges
if (Account.Ping.Rp > 0)
{
//load new messanges
for (int i = 0; i < Account.Ping.Rp; i++)
{
#region load rp
try
{
Rp message = _service.LoadRp(Account);
if (message != null)
{
//show messages
}
}
catch (Exception exception)
{
if (exception.Message == "You haven’t any messanged")
{
}
throw exception;// how handle show this exception in view?
}
#endregion
}
}
}
}
I have service class in external assembly, I inject this class in view model class with MEF. I need call service method every 3-4 seconds from view model.
I get from service new data as Dictionary. This Dictionary is bind to listbox in view. And I need refresh with this data listbox in view.
In my solution I use DispatcherTimer, but I am absolute begginer in calibur.micto also MVVM and WPF. I don’t know what is a suitable solution in my case. So if someone have advance I will be gratefull.
My solution is here:
[Export("MainScreen", typeof(IMainViewModel))]
public class MainViewModel : Screen, IMainViewModel
{
[Import]
private Service _service;//import with MEF from external assembly
[Import]
private Connection _conn;//import with MEF from external assembly
//this dictionary is bind to the listbox in view
private MyObservableDictionary<string, User> _users = null;
//temp dictionry
private MyObservableDictionary<string, User> _freshUsers = null;
private int _selectedUserIndex;
private DispatcherTimer _dispatcherTimer;
public Account Account{ get; set;}
public int SelectedUsersIndex
{
get { return _selectedUserIndex; }
set
{
_selectedUserIndex = value;
NotifyOfPropertyChange("SelectedUsersIndex");
}
}
public MainViewModel()
{
_dispatcherTimer = new DispatcherTimer();
_dispatcherTimer.Tick += DispatcherTimer_Tick;
_dispatcherTimer.Interval = TimeSpan.FromSeconds(3);
_dispatcherTimer.Start();
}
//I get every 3-4 sec from server new JSON data and I need update with this data listbox in view
private void DispatcherTimer_Tick(object sender, EventArgs eventArgs)
{
//server ping, call service method
Account.Ping = _service.Ping(Account);
//Refresh data in dictionary
_freshUsers = _service.LoadUsers(Account);
_users.Clear();
SelectedUsersIndex = 1;
foreach (var freshUser in _freshUsers)
{
_users.Add(freshUser);
}
//check if you have new messanges
if (Account.Ping.Rp > 0)
{
//load new messanges
for (int i = 0; i < Account.Ping.Rp; i++)
{
#region load rp
try
{
Rp message = _service.LoadRp(Account);
if (message != null)
{
//show messages
}
}
catch (Exception exception)
{
if (exception.Message == "You haven’t any messanged")
{
}
throw exception;// how handle show this exception in view?
}
#endregion
}
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
DispatcherTimer 正在您的 UI 线程上运行,因此当它运行您的检查时,您的 UI 可能会在 DispatcherTimer_Tick 消息运行时冻结。如果 DispatcherTimer_Tick 需要 2 秒才能运行,那么每 3 秒您就会将 UI 冻结 2 秒。用户不会喜欢这样。
所有服务调用都应该在非 UI 线程上完成,这样就不会锁定 UI,因此我建议使用计时器并执行如下操作:
这里我们使用系统计时器来检查不同的线程,因此您的 UI 将不会受到任何处理的影响。当我们想要通知 UI 发生了更改时,我们可以使用 _dispatcher(我们在构造函数中创建的 UI 调度程序)来“BeginInvoke”UI 线程上的方法。
这将使您的应用程序显示得更快。一个好的经验法则是尽可能远离 Dispatcher 线程;仅当您使用 UI 执行某些操作时才使用它。所有其他处理都应该在后台线程上进行。
希望这有帮助
The DispatcherTimer is running on your UI thread so while it is running your check your UI will probably freeze while the DispatcherTimer_Tick message runs. If the DispatcherTimer_Tick takes 2 seconds to run then every 3 seconds you freeze the UI for 2 seconds. Users won't like that.
All service calls should be done on a non-UI thread so that you don't lock up the UI so I'd suggest using a timer and doing something like this:
Here we're using a system timer to check for changes on a different thread, so your UI will be unaffected by any processing. When we want to notify the UI that a change has occured we can use the _dispatcher (the UI dispatcher we create in the constructor) to "BeginInvoke" a method on the UI thread.
This will make your app appear faster. A good rule of thumb is to keep off the Dispatcher thread as much as possible; only use it when you're doing something with the UI. All other processing should be on a background thread.
Hope this helps