Gun*_*ter 5 c# timer viewmodel caliburn.micro
我在外部程序集中有服务类,我在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
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
该DispatcherTimer是在你的UI线程运行,所以当它运行您的支票,而你的用户界面可能会冻结DispatcherTimer_Tick消息运行.如果DispatcherTimer_Tick需要2秒才能运行,那么每隔3秒就会冻结UI 2秒钟.用户不会喜欢这样.
所有服务调用都应该在非UI线程上完成,这样你就不会锁定UI,所以我建议使用一个计时器并执行以下操作:
public MainViewModel()
{
_stTimer = new System.Threading.Timer(Timer_Tick,null,3000,3000);
_dispatcher = Dispatcher.CurrentDispatcher;
}
private void Timer_Tick(object sender)
{
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);
}
for(int i=0;i<Account.Ping.Rp; i++)
{
//check if you have new messanges
if (Account.Ping.Rp > 0)
{
Rp message = _service.LoadRp(Account);
_messages.Add(message);
}
}
_dispatcher.BeginInvoke((Action)(()=>{OnPropertyChanged("Messages");}));
}
Run Code Online (Sandbox Code Playgroud)
这里我们使用系统计时器来检查不同线程上的更改,因此您的UI将不受任何处理的影响.当我们想要通知UI发生了更改时,我们可以使用_dispatcher(我们在构造函数中创建的UI调度程序)在UI线程上"BeginInvoke"一个方法.
这将使您的应用显得更快.一个好的经验法则是尽可能地避开Dispatcher线程; 只有在用UI做某事时才使用它.所有其他处理应该在后台线程上.
希望这可以帮助