分享初学者的第一个WPF应用程序——Timer线程时时刷新当前系统时间赋值于相关属性,并将其值绑定于TextBlock的Text属性


这个例子嘛是源于《WPF专业编程指南》(李应保著),这是我学习WPF以来看到第一个比较具体的例子,也是我在VS开发环境中写的第一个例子,感觉这个例子不错(当然书中还有几处错误)、能把好多知识点都连贯起来,所以献丑与大家分享一下,哈哈…

先看一下效果图吧:

接下来看看XAML中代码吧,挺少的,因为界面也挺简单的

XAML部分代码
<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。

partial 类部分代码
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);
}

}
}
 

自定义类扩展BlockText代码
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) 改天关注一下数据绑定语法。

呵呵…… 都没有注意到时间九点了啊,该工作了、改天继续……




 



返回导读目录,阅读更多随笔



分割线,以下为博客签名:

软件臭虫情未了
  • 编码一分钟
  • 测试十年功


随笔如有错误或不恰当之处、为希望不误导他人,望大侠们给予批评指正。

原文地址:https://www.cnblogs.com/08shiyan/p/1824696.html