Reputation: 185
I am trying to write a simple MVVM application. The expectation of this sample is to show up the time on the screen.
The xaml designer showed the time once in the designer
but when I run the app, I dont see the time on the screen at all. Could you please help me find what the issue is? I am attaching the code here.
MainWindow.xaml
<Window x:Class="WPFDigitalClock.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPFDigitalClock"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:ClockVM/>
</Window.DataContext>
<Grid>
<StackPanel>
<TextBlock Foreground="White" Background="Black" FontSize="30" TextAlignment="Center" Text="{Binding Path=DisplayTime}"/>
</StackPanel>
</Grid>
</Window>
MainWindow.xaml.cs
using System.Windows;
namespace WPFDigitalClock
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}
ClockVM.cs
using System;
using System.ComponentModel;
using System.Windows.Threading;
namespace WPFDigitalClock
{
class ClockVM : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private ClockModel clockModel;
DispatcherTimer Timer = new DispatcherTimer();
public string DisplayTime { get; set; }
public ClockVM()
{
clockModel = new ClockModel();
DisplayTime = "";
Timer.Interval = new TimeSpan(0, 0, 1);
Timer.Tick += new EventHandler(Timer_Click);
Timer.Start();
}
private void Timer_Click(object sender, EventArgs e)
{
DisplayTime = clockModel.Hour + ":" + clockModel.Minute + ":" + clockModel.Second;
if (PropertyChanged != null)
{
PropertyChanged(sender, new PropertyChangedEventArgs("DisplayTime"));
}
}
}
}
ClockModel.cs
using System;
namespace WPFDigitalClock
{
class ClockModel
{
public string Hour
{
get { return DateTime.Now.Hour.ToString(); }
}
public string Minute
{
get { return DateTime.Now.Minute.ToString(); }
}
public string Second
{
get { return DateTime.Now.Second.ToString(); }
}
}
}
Upvotes: 2
Views: 56
Reputation: 38134
Cannot reproduce your error. I've just added a counter and it updates perfectly.
int counter = 0;
private void Timer_Tick(object sender, EventArgs e)
{
DisplayTime = clockModel.Hour + ":" + clockModel.Minute + ":" +
clockModel.Second + " Counter:" + counter++.ToString();
OnPropertyChanged("DisplayTime");
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
My xaml is:
<Window x:Class="DataGridSelectedItemsWpfApplication.MainWindow"
<!--The code omitted for the brevity-->
xmlns:vm="clr-namespace:DataGridSelectedItemsWpfApplication.ViewModel"
Title="MainWindow" WindowStartupLocation="CenterScreen" Height="350" Width="525">
<Window.DataContext>
<vm:MyViewModel/>
</Window.DataContext>
<Grid>
<TextBlock Text="{Binding DisplayTime}"/>
</Grid>
</Window>
The model is the same like your model.
This works like this:
Update:
As @KyloRen says correctly about your mistake. Just change from
PropertyChanged(SENDER, new PropertyChangedEventArgs(propertyName));
TO
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
. It means that you raise an event from ClockVM
.
Upvotes: 1
Reputation: 8823
Problem is with how you have Raised the change of property DisplayTime
. use belowDispatcherTimer.Tick
handler as:
private void Timer_Click(object sender, EventArgs e)
{
DisplayTime = clockModel.Hour + ":" + clockModel.Minute + ":" + clockModel.Second;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("DisplayTime"));
}
}
You have passed the
sender
object as argument inPropertyChanged
method. It expect owner class of PropertyDisplayTime
insender
argument.
Upvotes: 3