C#WPF MVVM中的时间滴答

时间:2015-07-01 11:37:32

标签: c# wpf mvvm time ticker

我正在做一个程序,每秒必须挂一个时钟,主要问题是我是WPF和MVVM的初学者:)

但是我的时钟运行起来并不令人耳目一新。我只有时间和日期目的的特殊课程。

这是我的代码:

TimeDate类:

public class TimeDate : ViewModelBase
{

    public string SystemTimeHours;
    string SystemTimeLong;
    string SystemDateLong;
    string SystemTimeZoneLong;

    string SystemTimeShort;
    string SystemDateShort;
    string SystemTimeZoneShort;



    public void InitializeTimer()
    {

        DispatcherTimer timer = new DispatcherTimer();
        timer.Interval = TimeSpan.FromSeconds(1);
        timer.Tick += new EventHandler(timer_Tick);
        timer.Start();
    }

    void timer_Tick(object sender, EventArgs e)
    {

        SystemTimeHours = DateTime.Now.ToString("HH:mm tt");

    }
}

视图模型:

public class ViewModel : ViewModelBase
{
    public ViewModel()
    {
        TimeDate td = new TimeDate();
        td.InitializeTimer();
        HoursTextBox = td.SystemTimeHours;

    }



    private string _hourstextbox;
    public string HoursTextBox
    {
        get
        { return _hourstextbox; }
        set
        {
            if (value != _hourstextbox)
            {
                _hourstextbox = value;
                NotifyPropertyChanged("HoursTextBox");
            }
        }
    }
}

还有ViewModelBase中的NotifyProperty:

public class ViewModelBase : INotifyPropertyChanged, IDisposable
{
    #region Constructor

    protected ViewModelBase()
    {
    }

    #endregion // Constructor

    #region DisplayName


    public virtual string DisplayName { get; protected set; }

    #endregion // DisplayName

    #region Debugging Aides

    [Conditional("DEBUG")]
    [DebuggerStepThrough]
    public void VerifyPropertyName(string propertyName)
    {
        // Verify that the property name matches a real,  
        // public, instance property on this object.
        if (TypeDescriptor.GetProperties(this)[propertyName] == null)
        {
            string msg = "Invalid property name: " + propertyName;

            if (this.ThrowOnInvalidPropertyName)
                throw new Exception(msg);
            else
                Debug.Fail(msg);
        }
    }


    protected virtual bool ThrowOnInvalidPropertyName { get; private set; }

    #endregion // Debugging Aides

    #region INotifyPropertyChanged Members


    public event PropertyChangedEventHandler PropertyChanged;


    /// <param name="propertyName">The property that has a new value.</param>
    protected virtual void NotifyPropertyChanged(string propertyName)
    {
        this.VerifyPropertyName(propertyName);

        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null)
        {
            var e = new PropertyChangedEventArgs(propertyName);
            handler(this, e);
        }
    }

    protected virtual void NotifyPropertyChangedAll(object inOjbect)
    {
        foreach (PropertyInfo pi in inOjbect.GetType().GetProperties())
        {
            NotifyPropertyChanged(pi.Name);
        }
    }
    public virtual void Refresh()
    {
        NotifyPropertyChangedAll(this);
    }
    #endregion // INotifyPropertyChanged Members

    #region IDisposable Members

    public void Dispose()
    {
        this.OnDispose();
    }

    /// <summary>
    /// Child classes can override this method to perform 
    /// clean-up logic, such as removing event handlers.
    /// </summary>
    protected virtual void OnDispose()
    {
    }


    /// </summary>
    ~ViewModelBase()
    {
        string msg = string.Format("{0} ({1}) ({2}) Finalized", this.GetType().Name, this.DisplayName, this.GetHashCode());
        System.Diagnostics.Debug.WriteLine(msg);
    }


    #endregion // IDisposable Members

}

怎么办,那个时钟会每秒刷新一次?请帮忙

3 个答案:

答案 0 :(得分:2)

作为MSDN:

  

使用与System.Timers.Timer相对的DispatcherTimer的原因是DispatcherTimer在与Dispatcher相同的线程上运行,并且可以在DispatcherTimer上设置DispatcherPriority。

我做了更短的例子:

XAML:

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }

    public class ViewModel : ViewModelBase
    {
        private string _currentTime;

        public DispatcherTimer _timer;

        public string CurrentTime
        {
            get
            {
                return this._currentTime;
            }
            set
            {
                if (_currentTime == value)
                    return;
                _currentTime = value;
                OnPropertyChanged("CurrentTime");
            }
        }

        public ViewModel()
        {
            _timer = new DispatcherTimer(DispatcherPriority.Render);
            _timer.Interval = TimeSpan.FromSeconds(1);
            _timer.Tick += (sender, args) =>
                           {
                               CurrentTime = DateTime.Now.ToLongTimeString();
                           };
            _timer.Start();
        }
    }

    public class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName = null)
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

CS:

onAlert

enter image description here

希望得到这个帮助。

答案 1 :(得分:0)

您必须将DispatcherTimer指定为viewmodel类中的字段,而不仅仅是ctor中的局部变量。

垃圾收集器会在超出范围时销毁所有局部变量。

这是我对时钟的实现:)

public class MainWindowViewModel : ViewModelBase
{
    private readonly DispatcherTimer _timer;

    public MainWindowViewModel()
    {
        _timer = new DispatcherTimer {Interval = TimeSpan.FromSeconds(1)};
        _timer.Start();
        _timer.Tick += (o, e) => OnPropertyChanged("CurrentTime");
    }

    public DateTime CurrentTime { get { return DateTime.Now; } }
}

<TextBlock Text="{Binding CurrentTime, StringFormat={}{0:HH:mm tt}}" />

答案 2 :(得分:0)

时钟的静态包装器及其绑定示例:

using System.Threading;
    public static class ClockForWpf
    {
        private static readonly Timer timer = new Timer(Tick, null, 0, 10);
 
        private static void Tick(object state)
        {
            Time = DateTime.Now;
            TimeChanged?.Invoke(null, EventArgs.Empty);
        }
        public static event EventHandler TimeChanged;
        public static DateTime Time { get; private set; }
    }
        <TextBlock Text="{Binding Path=(local:ClockForWpf.Time)}"/>