2014-12-08 167 views
1

我有一个文本日志文件,我解析每10秒在WPF应用程序上显示它的值,我想在WPF中第一次使用MVVM。我面临的问题是我无法用计时器刷新DataContext。 文本文件的格式是定时器更新MVVM-WPF中的DataContext

log.txt的

用户名| RP1 | MS9 | 1.25

用户名| RP5 | MS7 | 1.03

代码的应用程序

Model-Class代码

public class UserModel 
{ 
    public string userID{get; set;} 
    public string RP{get; set;} 
    public string MS{get; set;} 
    public string Rate{get; set;} 
} 

代码模型视图级

public class AppModelView 
{ 
    private ObservableCollection<UserModel> _userList; 
    DispatcherTimer LogTimer; 

    public AppModelView() 
    { 
      _userList = new ObservableCollection<UserModel>(); 
      LogTimer = new DispatcherTimer(); 
      LogTimer.Interval = TimeSpan.FromMilliseconds(10000); 

      LogTimer.Tick += (s, e) => 
      { 
      foreach(DataRow row in LogManager.Record) //LogManager is class which parse the txt file and assign value into a DataTable Record 
        _userList.add(new UserModel 
        { 
         userID= row[0].toString(); 
         RP = row[1].toString(); 
         MS = row[2].toString(); 
         rate = row[3].toString(); 

        }); 
      }; 
      LogTimer.Start(); 
    } 

    public ObservableCollection<UserModel> UserList 
    { 
      get { return _userList; } 
      set { _userList = value; 
       NotifyPropertyChanged("UserList");} 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    public void NotifyPropertyChanged(string propName) 
    { 
     if (this.PropertyChanged != null) 
      this.PropertyChanged(this, new PropertyChangedEventArgs(propName)); 
    } 
} 

MainWindows.xaml

<Window x:Class="MonitoringSystem.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Monitoring Server" WindowStartupLocation="CenterScreen" Height="768" WindowState="Maximized" > 

    <Grid> 
    <DockPanel> 
      <Label Content="User Monitored" DockPanel.Dock="Top"/> 
      <ListView Name="lstRpt" DockPanel.Dock="Bottom" ItemsSource="{Binding UserList}" > 
       <ListView.View> 
        <GridView> 
         <GridViewColumn Header="UserID" DisplayMemberBinding="{Binding userID}"/> 
         <GridViewColumn Header="RP" DisplayMemberBinding="{Binding RP}"/> 
         <GridViewColumn Header="MS" DisplayMemberBinding="{Binding MS}"/> 
         <GridViewColumn Header="Rate" DisplayMemberBinding="{Binding Rate}"/> 
        </GridView> 
       </ListView.View> 
      </ListView> 
     </DockPanel> 
    </Grid> 
</Windows> 

MainWindows.xaml.cs

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     AppViewModel VM = new AppViewModel(); 
     this.DataContext = VM; 
    } 
} 

现在,如果我除去DispatcherTimer它显示的是数值第一次解析并显示它,但是使用定时器它不能显示任何值。 非常感谢您的指导。只有在视图模型需要

+0

无法刷新DataContext的 - 这是什么意思?代码似乎没问题。如果有任何更改,ListView将每10秒显示更改。 – Jawahar 2014-12-08 06:32:18

+0

@XAMLLover我无法获取表单上的任何值,如果我删除了dispatchertimer,那么它将首次解析这些值并在窗体上显示 – WiXXeY 2014-12-08 06:35:12

+0

@WiXXeY:显示代码,该代码填充新的“UserModel”属性。你不想改变数据上下文,你想更新用户列表,不是吗?另外,为什么'UserList'是可读写的?谁应该分配它,而不是'AppModelView'实例本身? – Dennis 2014-12-08 06:39:19

回答

1

我怀疑正在发生的事情是,你UserModel是被添加到该集合的属性已设置之前,因为你的UserModel没有INPC的观点从来没有更新一次他们被设置。

试着改变你的代码:

LogTimer.Tick += (s, e) => 
{ 
    foreach(DataRow row in LogManager.Record) //LogManager is class which parse the txt file and assign value into a DataTable Record 
    { 
     var userModel = new UserModel 
     { 
      userID= row[0].toString(); 
      RP = row[1].toString(); 
      MS = row[2].toString(); 
      rate = row[3].toString(); 
     }; 

     _userList.Add(userModel); 
    }; 

    LogTimer.Start(); 
}; 
1

修正

public class AppModelView 
    { 
     private ObservableCollection<UserModel> _userList; 
     DispatcherTimer LogTimer; 

     public AppModelView() 
     { 
      _userList = new ObservableCollection<UserModel>(); 
      LogTimer = new DispatcherTimer(); 
      LogTimer.Interval = TimeSpan.FromMilliseconds(10000); 

      LogTimer.Tick += (s, e) => 
      { 
       Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Normal, 
       new Action(
        delegate() 
        { 
         UserList.Add(new UserModel 
         { 
          userID = "test" 
         }); 
        } 
       ) 
       ); 
      }; 
      LogTimer.Start(); 
     } 

     public ObservableCollection<UserModel> UserList 
     { 
      get { return _userList; } 
      set 
      { 
       _userList = value; 
       NotifyPropertyChanged("UserList"); 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 

     public void NotifyPropertyChanged(string propName) 
     { 
      if (this.PropertyChanged != null) 
       this.PropertyChanged(this, new PropertyChangedEventArgs(propName)); 
     } 
    } 
+0

为什么要在DispatcherTimer的回调中使用调度器来运行新的委托,而这又会使用调度器开火? – Dennis 2014-12-08 06:53:41

+0

嗨,还没有检查。它也可以在没有调度员的情况下工作。问题与_userList。改为使用UserList集合 – 2014-12-08 07:48:09