我是WPF的新手,我正在尝试制作一个简单的应用程序,一个秒表。如果我没有进行数据绑定,它可以正常工作。这是我的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>
,这是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();
}
}
这是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));
}
}
}
我不知道我哪弄错了。
编辑:我搞定了。所以这是任何人参考的工作代码。
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">
<Grid> // partial code
并在后面的代码中,根据Erno的建议更改构造函数。
public MainWindow()
{
InitializeComponent();
viewModel = new StopWatchViewModel();
this.DataContext = viewModel;
}
谢谢你们!
答案 0 :(得分:4)
您的问题是,您没有任何机制让WPF知道您的属性已更新。基本上你有两个选择:
INotifyPropertyChanged
,以便让GUI知道消息何时更新。为了确保您拥有让INotifyPropertyChanged
工作的所有部分,请检查您是否完成了所有这些:
PropertyChanged
。NotifyPropertyChanged
方法来举起活动。此方法应采用字符串参数(属性的名称)并引发如下事件:PropertyChanged(this, new PropertyChangedEventArgs(<nameofproperty>)
。制作此方法的原因是将空检查和调用详细信息放在一个位置。NotifyPropertyChanged
。答案 1 :(得分:3)
只需像这样替换你的Message属性,它就会起作用:
public string Message
{
get { return (string)GetValue(MessageProperty); }
set { SetValue(MessageProperty, value); }
}
public static readonly DependencyProperty MessageProperty =
DependencyProperty.Register("Message", typeof(string),
typeof(MainWindow), new UIPropertyMetadata(String.Empty));
在发布我的解决方案后编辑我注意到您已将所有代码更改为ViewModel解决方案...随意忽略或返回到您的第一组代码。
在新代码中,您将创建ViewModel的两个实例,一个在代码中,另一个在资源中。这是不好的,因为你正在操作代码中的那个并绑定到资源中的那个(xaml)
修改强> 将构造函数更改为:
public MainWindow()
{
InitializeComponent();
stopwatch = new StopWatchViewModel();
this.DataContext = stopwatch;
}
这就是全部
答案 2 :(得分:1)
如果未正确实现INotifyPropertyChanged,则不会注意到对属性的更改。所以你应该先做。也许你早些时候错过了什么。