I'm new to WPF and I'm trying to make a simple app, a stopwatch. It works fine if I'm not doing the data binding. Here's my XAML.
<Window x:Class="StopWatch.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:StopWatch"
Title="MainWindow" Height="318" Width="233">
<Window.Resources>
<s:StopWatchViewModel x:Key="swViewModel" x:Name="swViewModel"></s:StopWatchViewModel>
</Window.Resources>
<Grid DataContext="{StaticResource swViewModel}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="128*" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="1" Height="49" HorizontalAlignment="Left" Margin="42,50,0,0" Name="txtTime" Text="{Binding Path=Message}" VerticalAlignment="Top" Width="147" FontSize="20" TextAlignment="Center" />
<Button Content="Start" Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="12,15,0,0" Name="startBtn" VerticalAlignment="Top" Width="58" Click="startBtn_Click" />
<Button Content="Stop" Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="76,15,0,0" Name="stopBtn" VerticalAlignment="Top" Width="58" Click="stopBtn_Click" />
<Button Content="Reset" Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="140,15,0,0" Name="resetBtn" VerticalAlignment="Top" Width="59"/>
</Grid>
and here is the code in MainWindow
public partial class MainWindow : Window
{
private StopWatchViewModel stopwatch;
public MainWindow()
{
InitializeComponent();
stopwatch = new StopWatchViewModel();
}
private void startBtn_Click(object sender, RoutedEventArgs e)
{
stopwatch.Start();
}
private void stopBtn_Click(object sender, RoutedEventArgs e)
{
stopwatch.Stop();
}
}
and here's the code in StopWatchViewModel.cs
class StopWatchViewModel : INotifyPropertyChanged
{
private DispatcherTimer timer;
private Stopwatch stopwatch;
private string message;
public event PropertyChangedEventHandler PropertyChanged;
public string Message
{
get
{
return message;
}
set
{
if (message != value)
{
message = value;
OnPropertyChanged("Message");
}
}
}
public StopWatchViewModel()
{
timer = new DispatcherTimer();
stopwatch = new Stopwatch();
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
stopwatch.Reset();
}
public void Start()
{
stopwatch.Start();
}
public void Stop()
{
stopwatch.Stop();
}
private void timer_Tick(object sender, EventArgs e)
{
Message = stopwatch.Elapsed.ToString(); // Doesn't work.
// Message = "hello"; does not work too!
}
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
I don't know where I got it wrong.
EDIT: I got it working. So here's the working code for anyone's reference.
XAML, change the original to this
<Window x:Class="StopWatch.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:StopWatch"
Title="MainWindow" Height="318" Width="233">
<Grid> // partial code
and in behind code, change the constructor based on Erno's suggestion.
public MainWindow()
{
InitializeComponent();
viewModel = new StopWatchViewModel();
this.DataContext = viewModel;
}
Thanks guys!
Your problem here is that you don't have any mechanism for letting WPF know that your property is updated. Basically you have two options here:
INotifyPropertyChanged so that it let's the GUI know when the message have been updated.To make sure that you have all parts for getting INotifyPropertyChanged to work, check that you did all of this:
PropertyChanged.NotifyPropertyChanged method to raise the event. This method should take a string parameter (name of the property) and raise the event like this : PropertyChanged(this, new PropertyChangedEventArgs(<nameofproperty>). The reason to make this method is to put the null check and invocation details in one place.NotifyPropertyChanged with the correct name (case-sensitive) of the property after the value has changed.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With