实现 INotifyPropertyChanged 接口可以在属性更改后通知数据的使用者,这个相信大伙儿都知道。于是,有朋友会问:对于要实时显示进度的情况,比如更新进度条,能用这个实现吗?

当然是可以的,也很简单,定义一个类,实现 INotifyPropertyChanged 接口,然后公开表示处理进度的属性,并且在属性更改后引发通知事件。

然后把该类的实例与进度条进行绑定即可,和一般的绑定差不多。不过,有一点需要强调:通常是把属性更改通知发送给UI对象的,多数情况下,我们在处理一些耗时操作都会在另一个线程上执行,这就使得在实现这个接口时,引发PropertyChanged 事件的时候容易发生错误。为了避免错误发生,在实现接口时,应当用Dispatcher来引发事件,确保能在UI线程上执行。

一个比较不错的方法,是先弄个抽象类,让它实现 INotifyPropertyChanged 接口,后面你所定义的各种 Model 类就可以从这个抽象类派生,这样会相当省事。

比如这样:

    public abstract class NotifyPropertyChangedBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged; protected async void OnPropertyChanged([CallerMemberName] string propName = "")
{
await Window.Current.Dispatcher.RunAsync(CoreDispatcherPriority.High,
() =>
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
});
}
}

因为在引发属性更改通知时需要指定属性名称,咱们使用一个技巧,在 OnPropertyChanged 方法的参数上加一个 CallerMemberNameAttribute,这么一来,只要在被更改的属性的set方法中调用这个方法,就会自动把属性的名字传给参数了,也不用我们手动输,既免去繁杂工作,也不容易弄错。注意参数在附加CallerMemberNameAttribute后一定要给它一个默认值,说白了就是让这个参数变成可选参数,以方便运行时库在运行阶段修改它。

调用 Window.Current.Dispatcher.RunAsync 方法确保事件引发的代码是在UI线程上执行的,就不会出现因交叉线程更改用户界面而导致的异常。

好,上面说了一车的废话,下面我们来定义一个表示进度数据的类,主要包括进度的最大值、最小值,以及当前进度,这个类从刚才定义的 NotifyPropertyChangedBase 类派生。

    public sealed class ProgressData : NotifyPropertyChangedBase
{
private int _max, _min, _currvalue; public int Max
{
get { return _max; }
set
{
if (value != _max)
{
_max = value;
OnPropertyChanged();
}
}
} public int Min
{
get { return _min; }
set
{
if (value != _min)
{
_min = value;
OnPropertyChanged();
}
}
} public int CurrentValue
{
get { return _currvalue; }
set
{
if (value != _currvalue)
{
_currvalue = value;
OnPropertyChanged();
}
}
}
}

在用户界面上声明 ProgressBar 控件,然后绑定到上面类型的属性。

        <ProgressBar Name="pb" Height="25" Margin="3,30,5,2"
Maximum="{Binding Max}"
Minimum="{Binding Min}"
Value="{Binding CurrentValue}"
SmallChange="1.0"/>

如何让 ProgressData 实例与 ProgressBar 控件关联呢,这好办,因为有一个 DataContext 属性,它可以赋任何类型的值,然后控件中的绑定会从该属性的值中寻找数据。

下面我们来关联一下。

            m_progressdata = new ProgressData();
m_progressdata.Max = ;
m_progressdata.Min = ;
m_progressdata.CurrentValue = ;
this.pb.DataContext = m_progressdata;

注意看最后一行,不解释。

然后定义一个基于 Task 的异步方法,来模拟在新线程上处理数据。

        async Task TestSomethingAsync()
{
while (m_progressdata.CurrentValue < m_progressdata.Max)
{
m_progressdata.CurrentValue++;
await Task.Delay();
}
}

随后可以进行测试了。

        private async void OnClick(object sender, RoutedEventArgs e)
{
m_progressdata.CurrentValue = m_progressdata.Min;
Button btn = sender as Button;
btn.IsEnabled = false;
await TestSomethingAsync();
btn.IsEnabled = true;
}

至此,就完成进度的绑定了,当你在线程中处理进度时,你可以不用管UI上用什么来显示进度了,哪怕是用文本显示,或用进度条来显示,都无所谓,数据与界面分离。

看看效果,还是挺不错的。

这种方法除了在UWP中可用,同样适用于WPF项目,因为都是一脉相承的,所以老周一直坚持:只要WPF学好了,别的都好办

示例下载地址

【Win 10 应用开发】通过数据绑定更新进度条的更多相关文章

  1. android AsyncTask异步下载并更新进度条

    AsyncTask异步下载并更新进度条    //如果不是很明白请看上篇文章的异步下载 AsyncTask<String, Integer, String> 第一个参数:String 传入 ...

  2. WPF BackGroundWord 异步加载更新进度条示例

    <Window x:Class="AsynchronousLoading.MainWindow" xmlns="http://schemas.microsoft.c ...

  3. [wxWidgets]_[0基础]_[经常更新进度条程序]

    场景: 1. 非常根据程序的进展需要处理业务,以更新进度条,进度条的目的是为了让用户知道业务流程的进度.一个进度条程序更友好,让用户知道在程序执行.不是没有反应. 2. 现在更新见过这两种方法的进展. ...

  4. Handler实现线程之间的通信-下载文件动态更新进度条

    1. 原理 每一个线程对应一个消息队列MessageQueue,实现线程之间的通信,可通过Handler对象将数据装进Message中,再将消息加入消息队列,而后线程会依次处理消息队列中的消息. 2. ...

  5. AsyncTask用法解析-下载文件动态更新进度条

    1. 泛型 AysncTask<Params, Progress, Result> Params:启动任务时传入的参数,通过调用asyncTask.execute(param)方法传入. ...

  6. Xamarin XAML语言教程使用Progress属性数据绑定设置进度条进度

    Xamarin XAML语言教程使用Progress属性数据绑定设置进度条进度 开发者除了可以为ProgressBar定义的Progress属性直接赋双精度类型的值外,还可以通过数据绑定的方式为该属性 ...

  7. 【Win 10 应用开发】导入.pfx证书

    这个功能其实并不常用,一般开发较少涉及到证书,不过,简单了解一下还是有必要的. 先来说说制作测试证书的方法,这里老周讲两种方法,可以生成用于测试的.pfx文件. 产生证书,大家都知道有个makecer ...

  8. 【Win 10应用开发】Adaptive磁贴模板的XML文档结构

    在若干天之前,老周给大家讲了Adaptive Toast通知的XML模板,所以相应地,今天老周给大家介绍一下Adaptive磁贴的新XML模板. 同样道理,你依旧可以使用8.1时候的磁贴模板,在win ...

  9. 【Win 10 应用开发】RTM版的UAP项目解剖

    Windows 10 发布后,其实SDK也偷偷地在VS的自定义安装列表中出现了,今天开发人员中心也更新了下载.正式版的SDK在API结构上和以前预览的时候是一样的,只是版本变成10240罢了,所以大家 ...

随机推荐

  1. 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑

    阅读目录 前言 场景1的思考 场景2的思考 避坑方式 实践 结语 一.前言 在上一篇中(如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成),有一行注释的代码: public interfa ...

  2. Docker 第一篇--初识docker

    已经多年不写博客, 看完<晓松奇谈>最后一期猛然觉醒, 决定仔细梳理下自己这几年的知识脉络. 既然决定写, 那么首先就从最近2年热门的开源项目Docker开始.Docker 这两年在国内很 ...

  3. 【开源】.Net Api开放接口文档网站

    开源地址:http://git.oschina.net/chejiangyi/ApiView 开源QQ群: .net 开源基础服务  238543768 ApiView .net api的接口文档查看 ...

  4. 使用 Android Studio 检测内存泄漏与解决内存泄漏问题

    本文在腾讯技术推文上 修改 发布. http://wetest.qq.com/lab/view/63.html?from=ads_test2_qqtips&sessionUserType=BF ...

  5. js数组去重几种思路

    在一些后台语言中都内置了一些方法来处理数组或集合中重复的数据.但是js中并没有类似的方法,网上已经有一些方法,但是不够详细.部分代码来源于网络.个人总计如下:大致有4种思路 1)使用两次循环比较原始的 ...

  6. 2016/12/28_javascript

    今天学习的主要内容: javascript: 1.if语句,switch语句,while循环以及for循环: 1)if语句 if(boolean){}; if(boolean){} else if(b ...

  7. App 审核由于 IPv6 网络问题被拒

    昨天 提交App Store 的时候被拒了 We discovered one or more bugs in your app when reviewed on iPhone running iOS ...

  8. iOS开源项目周报1229

    由OpenDigg 出品的iOS开源项目周报第三期来啦.我们的iOS开源周报集合了OpenDigg一周来新收录的优质的iOS开发方面的开源项目,方便iOS开发人员便捷的找到自己需要的项目工具等. Ma ...

  9. redis大幅性能提升之使用管道(PipeLine)和批量(Batch)操作

    前段时间在做用户画像的时候,遇到了这样的一个问题,记录某一个商品的用户购买群,刚好这种需求就可以用到Redis中的Set,key作为productID,value 就是具体的customerid集合, ...

  10. ubuntu系统(华硕笔记本)屏幕亮度用Fn控制的调节设置

    亲测配置: 系统:Linux lite 3.2 x86_64(Ubuntu其他版本可参考修改) 笔记本:华硕(asus)1201N 达到的效果: 可以正常使用Fn+F5调暗,Fn+F6调亮. 设置步骤 ...