简体   繁体   中英

Timer to Update DataContext in MVVM-WPF

I have a text log File which i parse every 10 seconds to display it values on the WPF-Application, I am trying to use MVVM for the first time in WPF. The problem i am facing is I am unable to refresh the DataContext with the timer. The format of the text file is

log.txt

UserID|RP1|MS9|1.25

UserID|RP5|MS7|1.03

Code for the Application is given below

Code for 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;}
 }

Code for ModelView-Class

 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;
     }
 }

Now if I remove the DispatcherTimer it display the values which were parse for the first time and display it , but with timer it cannot display any values. Your Guidance is highly appreciated.

Correction needed only in ViewModel

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

What I suspect is happening is that your UserModel is getting added to the collection before its properties have been set, and because your UserModel has no INPC the view never updates once they are set.

Try changing your code to:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM