分享初学者的第一个WPF应用程序——Timer线程时时刷新当前系统时间赋值于相关属性,并将其值绑定于TextBlock的Text属性
这个例子嘛是源于《WPF专业编程指南》(李应保著),这是我学习WPF以来看到第一个比较具体的例子,也是我在VS开发环境中写的第一个例子,感觉这个例子不错(当然书中还有几处错误)、能把好多知识点都连贯起来,所以献丑与大家分享一下,哈哈…
先看一下效果图吧:
接下来看看XAML中代码吧,挺少的,因为界面也挺简单的
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<Window x:Class="TimeWPF.TimeWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local ="clr-namespace:TimeWPF"
Title="我的第一个WPF应用程序——获取当前时间" Height="350" Width="525">
<StackPanel>
<local:MyTextBlock Text="{Binding RelativeSource={x:Static Member=RelativeSource.Self},Path=Time}" FontSize="32" Background="Wheat"/>
<local:MyTextBlock Text="{Binding RelativeSource={x:Static Member=RelativeSource.Self},Path=Time}" Time="2010/09/30" FontSize="20" Background="White"/>
</StackPanel>
</Window>
上一部分代码呢,用到了数据绑定,由于对数据绑定的语法还不熟悉、弄了好长时间才弄出来。
下面嘛,毫无疑问了肯定是C#部分的代码了,如果你注意到了MyBlockText,那么你应该想到了这里的C#部分代码至少是两个类:一个是与XAML有关联的partial类,还有一个自定义类、它扩展了BlockText。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
namespace TimeWPF
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class TimeWindow : Window
{
/// <summary>
/// 声明一个委托用于新线程中使用它 去设定当前的系统时间
/// </summary>
/// <param name="dt"></param>
private delegate void SetTimeDelegate(DateTime dt);
/// <summary>
/// 计时器
/// </summary>
private Timer myTimer;
/// <summary>
/// 声明一个相关属性
/// </summary>
public static DependencyProperty TimeProperty;
/// <summary>
/// 静态够造函数
/// </summary>
static TimeWindow()
{
//实例化一个 属性与元数据间的关系实体
FrameworkPropertyMetadata meta = new FrameworkPropertyMetadata();
meta.Inherits = true; //标记依赖属性项是否可以被传递下去
meta.AffectsMeasure = true; //标记该属性可以影响布局
meta.DefaultValue = DateTime.Now;//设置默认值
meta.PropertyChangedCallback += new PropertyChangedCallback(OnTimePropertyChanged);
//注册一个可读可写的相关属性
TimeProperty = DependencyProperty.Register("Time",typeof(DateTime),typeof(TimeWindow),meta,new ValidateValueCallback(ValidateTimeProperty));
}
/// <summary>
/// 回调 验证方法
/// </summary>
/// <param name="obj">传入当前要被验证的属性值</param>
/// <returns>返回验证结果</returns>
public static bool ValidateTimeProperty(object obj)
{
DateTime dt = (DateTime)obj;
if (dt.Year < 2020 && dt.Year > 1990)
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// 属性值发生改变
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
public static void OnTimePropertyChanged(DependencyObject sender,DependencyPropertyChangedEventArgs args)
{
}
///// 定义一个CLR属性
///// </summary>
//public DateTime Time
//{
// set { SetValue(TimeProperty,value);}
// get { return (DateTime)GetValue(TimeProperty); }
//}
/// <summary>
/// 构造函数
/// </summary>
public TimeWindow()
{
InitializeComponent();
//启动新线程刷新相关属性 TimeProperty
myTimer = new Timer(new TimerCallback(RefreshTime), new AutoResetEvent(false), 0, 1000);//立即启动 每1000毫秒调用一次CallBack
}
/// <summary>
/// Timer CallBack 函数用于刷新当前的TimeProperty相关属性的属性值
/// </summary>
/// <param name="obj"></param>
private void RefreshTime(object stateInfo)
{
SetTimeDelegate d = new SetTimeDelegate(this.SetTime);
this.Dispatcher.BeginInvoke(d, System.Windows.Threading.DispatcherPriority.Send, DateTime.Now);
}
/// <summary>
/// 用当前时间 设置相关属性TimeProperty的值
/// </summary>
/// <param name="dt"></param>
private void SetTime(DateTime dt)
{
//this.Time = dt;
SetValue(TimeProperty, dt);
}
}
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Threading;
namespace TimeWPF
{
/// <summary>
/// 自定义TextBlock
/// </summary>
public class MyTextBlock :TextBlock
{
/// <summary>
/// 声明一个相关属性
/// </summary>
public static DependencyProperty TimeProperty;
/// <summary>
/// 静态构造函数
/// </summary>
static MyTextBlock()
{
//实例化一个属性与元数据间的关系
FrameworkPropertyMetadata meta = new FrameworkPropertyMetadata();
meta.Inherits = true;
//将另一类型 作为 已经注册的 依赖属性的所有者来添加
TimeProperty = TimeWindow.TimeProperty.AddOwner(typeof(MyTextBlock));
//重写特定类型上的元数据
TimeProperty.OverrideMetadata(typeof(MyTextBlock), meta);
}
public MyTextBlock() :base()
{
}
/// <summary>
/// MyTextBlock.TimeProperty
/// CLR属性
/// </summary>
public DateTime Time
{
set { SetValue(TimeProperty, value); }
get { return (DateTime)GetValue(TimeProperty); }
}
}
}
好了,代码大概就这些了,下面再写一些于之相关的东东吧。
(1)WPF应用程序提供了8个提供程序用于设置依赖属性的值它们的优先级从高到底依次为:
1、本地值;2、样式触发器;3、模板触发器;4、样式设置程序;5、主题样式设置程序;6、主题样式设置程序;7属性值传递;8、默认值;
(2) 改天关注一下数据绑定语法。
呵呵…… 都没有注意到时间九点了啊,该工作了、改天继续……