精华内容
下载资源
问答
  • 这是学习笔记的第1968篇文章我们认知中的巡检设计大多是一种被动的方式,即你希望做什么,按照这个思路和流程来设计,如果希望巡检能够发挥出强有力的支撑,那么我们需要转化...
        

    这是学习笔记的第 1968 篇文章


    我们认知中的巡检设计大多是一种动的方式,即你希望做什么,按照这个思路和流程来设计,如果希望巡检能够发挥出强有力的支撑,那么我们需要转化被动为主动,即思考巡检数据对我们有什么用处?

    有的同学可能还不大理解,我们来举个例子,比如我们会每天收集数据库中的表信息(数据库,表名,表数据大小,索引大小,表结构变更时间,碎片情况等),这样一份看起来简单的数据如何发挥余热的,我来给出一个列表:

    1)冷数据一些长时间未操作的数据可以通过数据量和时间维度进行权衡

    2)库中的表过多可以通过统计的方式得知哪些环境是属于不规范环境,这类问题通常感受不到,但是一出问题哪里都是问题

    3)一些没有用到的表,临时表和备份表这些表像牛皮癣一样,我们要对数据库做下清理。

    4)周期表探测,如果一些业务存在周期表需求,那么通过反向的方式可以很轻松找出那些日报,月表等周期表

    5)数据库的特性和业务类型不匹配如果表数据写入过多,很可能是日志型业务,可以根据一个或多个维度来评估是否和现有的业务类型匹配

    6)预测数据量变化可以通过历史数据的变化建立模型预测近一段时间的数据量变化

    7)数据生命周期管理,有了时间维度的信息,我们可以建立数据生命周期管理模型,来通过多个维度来进行表结构变更的追溯。

    8)权限和安全隐患管理,我们可以通过全局的方式来评估现有环境存在的隐患,比如那些流程外创建出的表,流程外删除的表,可以做得统筹的管理。

    以上只是抛砖引玉,主要想表达的就是巡检在一定阶段之后产生数据分析的更大价值,让我们对更多的问题具有主动的管理方式,而从一开始就希望想全,想好也是不切实际的。

        此外,我需要补充的就是运维体系的建设中需要深入融合巡检。

    我们的运维体系中,其实一直有一块短板,那就单纯依靠监控报警模块,工作效率和质量是一种被动的方式。

    我们可以假设一个场景,你在节假日的时候在外面游玩,刚在高速路上的时候,收到了一条报警,一个关键业务系统的磁盘空间超出阈值(假设是80%),这对你的旅游兴致来说是大受影响,虽然这样一件事情处理的难度不高,但是我们总是需要花费那么些额外的时间和精力去处理,这个代价对于个人来说是很高的。

    如果我们能够有一种机制去缓解这个问题,比如我们马上收到巡检信息提示的一封邮件,可以看到这个磁盘空间的增长是平缓的,而不是那种业务增长导致的尖峰,那么这个问题处理的时间就可以适当后延,对于正常的生活和工作是收益很大的,按照这种机制,在不影响业务的前提下,我们可以把很多干扰我们的大量碎片时间,作为一种延迟处理的方式,这是一种运维信仰和工作理念。

    以下是一个监控,报警,巡检的三体一体集成方案。

    640?wx_fmt=png

    我们来这个做下解释

    1)监控报警这是常规的运维体系,监控达到阈值触发报警

    2)报警巡检通过报警能够异步调用巡检接口,已有的数据库业务进行巡检,比如发送巡检可视化报告或者巡检提示信息,让巡检工作不再被动,而是因需而动

    3)巡检和监控,通过巡检机制的完善,能够发现更多的问题,然后建立新的监控指标

    4)监控和巡检,如果监控指标未达到报警阈值,并不一定意味着没问题,但是通过一些监控指标来触发巡检就可以把这块空白补上,比如一个系统的磁盘空间80%为阈值,1:00~2:00,磁盘空间使用率从20%增长到70%,虽然不会触发报警,但是短时间的增量较多,我们可以设定70%的阈值为巡检模型所用,就可以通过巡检模型来识别出这类问题

    640?

    展开全文
  • FPGA 配置两种模式:主动配置和被动配置方式,采用主动配置下,我们就需要一片 FLASH 来存储 FPGA 固件,那么我们在升级固件写 FLASH 的过程中如何避免因意外情况发生导致升级失败而使 FPGA 砖呢?下面就由笔者...

    FPGA 配置两种模式:主动配置和被动配置方式,采用主动配置下,我们就需要一片 FLASH 来存储 FPGA 固件,那么我们在升级固件写 FLASH 的过程中如何避免因意外情况发生导致升级失败而使 FPGA 变砖呢?下面就由笔者带领大家来挖山掘石、一探究竟。

    本文主要针对 Xilinx 的 Spartan-6 和 7-series FPGA。在设计 FPGA 的远程升级功能时,我们要实现以下两个指标:

    1、FPGA 具有升级功能,即在正常工作状态下,FPGA 可以将新的固件数据烧写到 FLASH 里面并在下次重启的时候能够正常加载;

    2、如果升级过程中出现意外情况,FLASH 里面原有的固件被破坏,那么 FPGA 能够从备份固件区启动配置,即 FLASH 里要有另外一份没有问题的固件备份,且 FPGA 可以自动跳转到这个固件区读取固件。

    好了,功能需求明确,下面就该潜下心来进行框架流程设计、时序设计、代码编写以及仿真验证了。一番辛苦劳作之后,IP 设计好了,这个时候心里暗暗自喜:应该没问题,只待硬件测试啦。三下五除二,找了台机器测试了一遍,发现能够正常升级,这个时候心里那个是乐开了花啊,一次搞定,哈哈。

    接下来就要进行激动人心的防砖测试了,于是你就邀请了周围的同事来一起见证奇迹,于是测试开始,于是在升级运行的过程中你自信的断了电,然后你对着周围的同事说:下面就是见证奇迹的时刻,于是你接通了电源,此时你笑的是那么春光灿烂。突然,你耳边传来一句轻轻的、温柔的耳语:老兄,你的 FPGA 变砖啦!“怎么可能!”,你不屑的低吼了一句,可是,当你看到那颗小小的 LED 灯安静的还在沉睡的时候,你傻眼了,“What the hell is going on!”,看着周围的同事,我理解你的心情:一种被狠狠打脸的刺痛感袭上了你的心头。你埋着头绷着脸,折腾了半天没找出原因在哪,这到底是怎么回事儿呢?

    FPGA 升级防砖也即支持 FALLBACK 模式,赛灵思官方的指导文档里也进行了相应的指导说明。对于 FALLBACK 模式,最重要的就是要构建起一个 FLASH 镜像文件,该镜像文件的架构如图 1 所示。

    图 1 FLASH 镜像文件架构

    关于 FLASH 镜像架构的信息,赛灵思官方的 configuraTIon user guide 里有详细说明。图中,MulTIboot Header 决定了 FPGA 上电之后要先从哪个固件区读取配置文件以及如果失败了该跳转到哪个固件区读取备份配置。我们的镜像里划分了两片区域用于存储固件,分别为:AcTIve 区和 Old(golden)区,我们的升级指的就是对 AcTIve 区的固件进行更新,Header 区和 Old 区的信息不改动;FPGA 每次上电先从 Active 区读取配置文件。Old 区是一份固件备份,它的作用就是当 Active 区因为升级意外而固件被破坏的情况下,FPGA 能够从此处启动配置。

    那么,如何保证当 Active 区的固件因为升级意外被破坏时 FPGA 能够主动切换到 Old 区域读取配置文件呢?这就是我们要说明的问题。

    FPGA 升级固件的烧写一般有两种方式,分别如下:

    1、顺序烧写,这是最传统的烧写方式,即不对固件进行任何更改直接往 FLASH 里烧写;

    2、调整固件烧写顺序,即对固件进行一定的修改,然后分两次烧写。

    我们在设计的时候首先想到的就是第一种方式,况且赛灵思官方文档也说了在如下情况下 FPGA 会跳转到备份区启动配置:

    1、读取配置文件的同步字超时,此时会触发跳转;

    2、检查到固件 CRC 出错,此时会触发跳转。

    根据这些说法,采用第一种方式也不会出问题啊!可是为什么就不行呢?也许细心测试的你会发现,在擦除的过程中断电的话 FPGA 能够从备份区启动,在烧写的过程中断电的话 FPGA 就会启动失败,你,有没有感悟到什么?是不是看到了一丝丝亮光?奥特曼说过:有光的地方就有希望!你可能会问:为什么有第二种烧写方式?要怎样调整固件呢?为什么要调整呢?在这里,我先给你肯定答案:采用第二种方式完全不会出问题。现在,我们接着往下卖关子。

    既然有上面的一系列疑问,那么我们就需要去研究一下 ISE 工具在生成固件的时候是怎样的一种打包格式。经过研究发现两个很重要的信息:

    1、配置文件的同步字在固件的首部;

    2、CRC 检查命令一般在固件的后部,而 FPGA 必须在收到 CRC 检查命令之后才会去检查 CRC 值。

    前面也提到,当擦除的时候断电 FPGA 能够发生配置跳转,当烧写的时候断电 FPGA 无法进行配置跳转,说到这里再结合上面的两条重要的发现,你也许已经为自己心中的疑问找到答案了吧?很显然,因为固件的同步字很少,所以能够很快被擦除也可以很快被写入 FLASH;因此,当擦除的时候断电了,此时固件的同步字已经破坏,而 FPGA 读不到同步字就会出现看门狗超时,那么此时 FPGA 就会跳转到备份区读取配置文件;当在烧写的时候断电呢?因为此时同步字已经被正确写入,而 CRC 检查命令被破坏了,FPGA 在配置的时候会去读 CRC 检查命令,直到读到为止,可是 CRC 检查命令被破坏了怎么办呢?没得办法啊,FPGA 有一种不撞南墙不回头,撞了南墙依然不回头的韧劲和坚持,它会一直读下去,所以它就陷入死循环了,哎!你说如果爱情里也有这种精神该多好啊!

    经过上面的解释,我们会恍然大悟:原来通过 CRC 错误触发 FPGA 配置跳转不靠谱啊!既然如此,我们就只能在固件的同步字上做文章了。好了,不卖关子了,其实,在固件的同步字上做文章也就对应着升级固件的烧写方式 2:修改固件并调整固件的烧写顺序,简单解释如下:

    1、把固件的同步字修改掉,第一步烧写的时候不烧同步字;

    2、当固件的其余部分烧写完毕之后再单独把固件的同步字烧写入原来对应的 FLASH 位置处。

    这样做了之后,无论是擦除过程中断电还是烧写的过程中断电,固件的同步字都会被破坏,那么肯定会触发 FPGA 的配置跳转,即 FALLBACK 一定会成功!小小剧透一下:赛灵思官网里的 AR 问答记录里也有相应的解决方案说明哦,自己去搜吧,祝你好运!

    展开全文
  • FPGA 配置两种模式:主动配置和被动配置方式,采用主动配置下,我们就需要一片 FLASH 来存储FPGA 固件,那么我们在升级固件写 FLASH 的过程中如何避免因意外情况发生导致升级失败而使 FPGA砖呢?下面就由笔者带领...

    FPGA 配置两种模式:主动配置和被动配置方式,采用主动配置下,我们就需要一片 FLASH 来存储FPGA 固件,那么我们在升级固件写 FLASH 的过程中如何避免因意外情况发生导致升级失败而使 FPGA变砖呢?下面就由笔者带领大家来挖山掘石、一探究竟。

    本文主要针对 Xilinx 的 Spartan-6 和 7-series FPGA。在设计 FPGA 的远程升级功能时,我们要实现以下两个指标:

    1、FPGA 具有升级功能,即在正常工作状态下,FPGA 可以将新的固件数据烧写到 FLASH 里面并在下次重启的时候能够正常加载;

    2、如果升级过程中出现意外情况,FLASH 里面原有的固件被破坏,那么 FPGA 能够从备份固件区启动配置,即 FLASH 里要有另外一份没有问题的固件备份,且 FPGA 可以自动跳转到这个固件区读取固件。

    好了,功能需求明确,下面就该潜下心来进行框架流程设计、时序设计、代码编写以及仿真验证了。一番辛苦劳作之后,IP 设计好了,这个时候心里暗暗自喜:应该没问题,只待硬件测试啦。三下五除二,找了台机器测试了一遍,发现能够正常升级,这个时候心里那个是乐开了花啊,一次搞定,哈哈。

    接下来就要进行激动人心的防砖测试了,于是你就邀请了周围的同事来一起见证奇迹,于是测试开始,于是在升级运行的过程中你自信的断了电,然后你对着周围的同事说:下面就是见证奇迹的时刻,于是你接通了电源,此时你笑的是那么春光灿烂。突然,你耳边传来一句轻轻的、温柔的耳语:老兄,你的 FPGA 变砖啦!“怎么可能!”,你不屑的低吼了一句,可是,当你看到那颗小小的 LED 灯安静的还在沉睡的时候,你傻眼了,“What the hell is going on!”,看着周围的同事,我理解你的心情:一种被狠狠打脸的刺痛感袭上了你的心头。你埋着头绷着脸,折腾了半天没找出原因在哪,这到底是怎么回事儿呢?

    FPGA 升级防砖也即支持 FALLBACK 模式,赛灵思官方的指导文档里也进行了相应的指导说明。对于 FALLBACK 模式,最重要的就是要构建起一个 FLASH 镜像文件,该镜像文件的架构如图 1 所示。

    图 1 FLASH 镜像文件架构

    关于 FLASH 镜像架构的信息,赛灵思官方的 configuraTIon user guide 里有详细说明。图中,MulTIboot Header 决定了 FPGA 上电之后要先从哪个固件区读取配置文件以及如果失败了该跳转到哪个固件区读取备份配置。我们的镜像里划分了两片区域用于存储固件,分别为:AcTIve 区和 Old(golden)区,我们的升级指的就是对 AcTIve 区的固件进行更新,Header 区和 Old 区的信息不改动;FPGA 每次上电先从 Active 区读取配置文件。Old 区是一份固件备份,它的作用就是当 Active 区因为升级意外而固件被破坏的情况下,FPGA 能够从此处启动配置。

    那么,如何保证当 Active 区的固件因为升级意外被破坏时 FPGA 能够主动切换到 Old 区域读取配置文件呢?这就是我们要说明的问题。

    FPGA 升级固件的烧写一般有两种方式,分别如下:

    1、顺序烧写,这是最传统的烧写方式,即不对固件进行任何更改直接往 FLASH 里烧写;

    2、调整固件烧写顺序,即对固件进行一定的修改,然后分两次烧写。

    我们在设计的时候首先想到的就是第一种方式,况且赛灵思官方文档也说了在如下情况下 FPGA 会跳转到备份区启动配置:

    1、读取配置文件的同步字超时,此时会触发跳转;

    2、检查到固件 CRC 出错,此时会触发跳转。

    根据这些说法,采用第一种方式也不会出问题啊!可是为什么就不行呢?也许细心测试的你会发现,在擦除的过程中断电的话 FPGA 能够从备份区启动,在烧写的过程中断电的话 FPGA 就会启动失败,你,有没有感悟到什么?是不是看到了一丝丝亮光?奥特曼说过:有光的地方就有希望!你可能会问:为什么有第二种烧写方式?要怎样调整固件呢?为什么要调整呢?在这里,我先给你肯定答案:采用第二种方式完全不会出问题。现在,我们接着往下卖关子。

    既然有上面的一系列疑问,那么我们就需要去研究一下 ISE 工具在生成固件的时候是怎样的一种打包格式。经过研究发现两个很重要的信息:

    1、配置文件的同步字在固件的首部;

    2、CRC 检查命令一般在固件的后部,而 FPGA 必须在收到 CRC 检查命令之后才会去检查 CRC 值。

    前面也提到,当擦除的时候断电 FPGA 能够发生配置跳转,当烧写的时候断电 FPGA 无法进行配置跳转,说到这里再结合上面的两条重要的发现,你也许已经为自己心中的疑问找到答案了吧?很显然,因为固件的同步字很少,所以能够很快被擦除也可以很快被写入 FLASH;因此,当擦除的时候断电了,此时固件的同步字已经破坏,而 FPGA 读不到同步字就会出现看门狗超时,那么此时 FPGA 就会跳转到备份区读取配置文件;当在烧写的时候断电呢?因为此时同步字已经被正确写入,而 CRC 检查命令被破坏了,FPGA 在配置的时候会去读 CRC 检查命令,直到读到为止,可是 CRC 检查命令被破坏了怎么办呢?没得办法啊,FPGA 有一种不撞南墙不回头,撞了南墙依然不回头的韧劲和坚持,它会一直读下去,所以它就陷入死循环了,哎!你说如果爱情里也有这种精神该多好啊!

    经过上面的解释,我们会恍然大悟:原来通过 CRC 错误触发 FPGA 配置跳转不靠谱啊!既然如此,我们就只能在固件的同步字上做文章了。好了,不卖关子了,其实,在固件的同步字上做文章也就对应着升级固件的烧写方式 2:修改固件并调整固件的烧写顺序,简单解释如下:

    1、把固件的同步字修改掉,第一步烧写的时候不烧同步字;

    2、当固件的其余部分烧写完毕之后再单独把固件的同步字烧写入原来对应的 FLASH 位置处。

    这样做了之后,无论是擦除过程中断电还是烧写的过程中断电,固件的同步字都会被破坏,那么肯定会触发 FPGA 的配置跳转,即 FALLBACK 一定会成功!小小剧透一下:赛灵思官网里的 AR 问答记录里也有相应的解决方案说明哦,自己去搜吧,祝你好运!

    展开全文
  • 那么被动交互如何让用户感觉流畅?这是今天第一个关于优化的话题。 被动交互如何让用户感觉流畅 我在京东上搜索显示器,发现有一个筛选条件叫刷新率,最低的是60HZ,高的可以达到165HZ以上...
  • 将朋辈教育的理念引入到学业辅导工作中,有助于引导大学生充分发挥主观能动性,以大连理工大学城市学院为例,如何培养学生以及培养什么样的学生是本文主要研究的内容,通过朋辈教育学生变被动学习为主动学习的过程。...
  • 但传统的程序设计都是 UI驱动程序 ,这反而使数据成为被动如何使数据反之为 主动 呢? WPF 的核心理念就是 数据驱动UI , 要想数据成功真正的核心,必须使用 Binding 机制。 文章目录 1. Binding 入门基础 ...

    用最少的文字来解释清楚每一行代码,加油 !


    程序 = 数据 + 算法, 数据一直处于核心地位
    但传统的程序设计都是 UI驱动程序 ,这反而使数据成为被动,如何使数据反变之为 主动 呢?
    WPF 的核心理念就是 数据驱动UI , 要想让数据成功真正的核心,必须使用 Binding 机制。


    下面的那些超链接没什么用,只是好看而已 ^ - ^
    

    【文章目录】


    要想进行下面的学习,我们最好理清一个基本的概念
    什么是源 ? 什么是目标 ? 什么是路径?
    我们把 Binding 比作数据的桥梁,那么它的两端分别是 Binding 的 源(Source)目标(Target)
    数据从哪里来哪里就是源,Binding是架在中间的桥梁,Binding目标是数据要往哪儿去,路径是数据源中需要绑定的属性是谁
    一般情况下,Binding源是逻辑层的对象,Binding 目标是UI层的控件对象,这样我们就完成了数据驱动UI的过程。

    我将通过下面的一些案例来详解 Binding的那些事 …


    【1. Binding 入门基础】

    有了这些基本的概念之后,我们尝试写一个简单的小例子,来感受一下 Binding的神奇之处 
    
    1. 首先,我们创建一个名为 Student的类,这个类的实例作为 数据源 的使用:
    class Student
    {
        private string name;	// 姓名
    
        public string Name
        {
            get {return name;}
            set {name = value;}
        }	
    }
    1. 链接接口:
      但是,当我们将这个 name的值改变时,UI元素怎么才能知道我们改变了呢?并且作出相应的变化 ?我们要做的是让作为:
      数据源的类实现 System.ComponentModel名称空间中的INotifyPropertyChanged 接口
      当为Bidning 设置了数据源后, Binding 就会自动侦听来自这个接口的 PropertyChanged事件
      我们将 Student类升级过后是这样的:
    class Student : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;	// 侦听的事件	    
    
        private string name;
    
        public string Name
        {
            get{return name;}
            set
            {
                name = value;
                // 激发事件
                if(this.PropertyChanged != null)
                {
                    // 告诉它名为 Name的属性发生了改变
                    this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name"));
                }
            }
        }	
    }
    1. 我们数据源部分已经写好,接下来我们准备两个 UI元素,TextBox 和 Button:
    <StackPanel>
    	<TextBox x:Name="textBoxName"  BorderBrush="Black"  Margin="5" />
    	<Button Content="Add Age"  Margin="5"  Click="Button_Click" />
    </StackPanel>

    界面大小自行设置,结果图如下:
    在这里插入图片描述

    1. 使用 Binding 把数据源和 UI元素连接起来:

    连接之前,我们首先在 MainWindow类里写出:
    Student student;
    为什么不在构造器里面写呢 ? 为了我们使用Button按钮的点击事件时,方便访问

    在 MainWindow 构造器中,写出如下的两行代码:

    student = new Student() { Name = "huameng" }  // 实例化对象
    
    // 第一个参数是 TextBox的依赖属性绑定到文本
    // 第二个实例化 Binding对象,参数为需要绑定的属性(路径), 设置数据源
    this.textBoxName.SetBinding(TextBox.TextProperty, new Binding("Name")
     { Source = student });
    1. 为Button 元素实现点击事件(修改数据源的属性):
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        student.Name += "nb";
    }
    1. 效果动画图如下:
      在这里插入图片描述

    【2. Binding 源与路径】

    “源” 亦或是万物的源头, Binding的源也就是数据的源头。Binding对源的要求并不苛刻 ——
    只要它是一个对象,并且通过属性(Property)公开自己的数据,它就能作为 Binding的源。


    2.1 —— 把控件作为 Binding 源与Binding标记扩展

    Binding 的源基本是逻辑层的对象,但有时候为了让 UI元素产生一些联动效果,也会使用Binding 在控件间建立关系。

    下面的代码把一个 TextBox的Text属性 关联在了 Slider的Value属性 上:

    <StackPanel>
    	<TextBox x:Name="textBox1"  Text="{Binding Path=Value, ElementName=slider1}"
    		BorderBrush="Black"  Margin="5" />
    	<Slider x:Name="slider1"  Maximum="100"  Minimum="0"  Margin="5" />
    </StackPanel>  

    与之等价的 TextBox的Binding, C#代码是:

    this.testBox1.SetBinding(TextBox.TextProperty, new Binding("Value")
    		{ElementName="slider1"};

    Binding类的构造器是可以接收 Path作为参数,所以XAML代码也可以这样写:

    <TextBox x:Name="textBox1"  Text="{Binding Value, ElementName=slider1}"
    	BorderBrush="Black"  Margin="5" />

    实现效果图如下:
    在这里插入图片描述

    绑定效果已经完成,但是我在最后尝试了改变 TextBox的Text,而 Slider的Value 没有立即显示出来,这是为什么呢? 答案在下一小节中揭晓 …


    2.2 —— 控制 Binding 方向及数据更新

    2.2.1 控制 Binding 方向

    很多的 UI元素是只读的,也就是 Binding中的源向目标的单向沟通 ,比如 TextBlock、Label等等
    也有些 UI元素是可读可写的,也就是可以支持 Binding中的目标向源的沟通,比如上一小节的 TextBox

    控制 Binding 数据流向的属性是 Mode,它的类型是 BindingMode枚举。
    BindingMode的取值为:

    - TwoWay
    - OneWay
    - OnTime
    - OneWayToSource
    - Default	(根据目标的实际情况确定,比如:**TextBox 双向、TextBlock 单向**
    

    比如我们将上一小节的TextBox代码增加一个单向模式,这样我们就不能通过修改TextBox的Text来改变 Slider的Value

    在这里插入图片描述

    2.2.2 数据更新

    这里,我们回想上一小节中的最后部分,修改TextBox的Text属性,Slider的Value属性没有立即更改,而是要把 索引光标(焦点) 移到别的地方才会修改属性值,这是为什么呢 ?

    这就引出了 Binding的另一个属性 —— UpdateSourceTrigger,它的类型是 UpdateSourceTrigger 枚举,取值为:

    - PropertyChanged
    - LostFocus
    - Explicit
    - Default  (与LostFocus一致,失去焦点后,改变)
    

    我们只需要将这个属性改为 PropertyChanged,Slider 的Value就会随着 TestBox的 Text改变而改变:
    在这里插入图片描述

    实现效果图 :

    在这里插入图片描述


    2.3 —— “没有 Path” 的 Binding

    当 Binding源本身就是数据的时候,是没有属性的,比如:string、int 等。

    这时,我们只需要将 Path的值设置为 “ . " ,而在XAML中 “ . "又可以省略不写,但是在C#代码中,是不能省略的,看下面的例子:

    <StackPanel>
    	<StackPanel.Resources>
    		<sys:String x:Key="str">Hello World!</sys:String>
            </StackPanel.Resources>
    
            <TextBlock x:Name="textBlock1" TextWrapping="Wrap" FontSize="20" 
            	Text="{Binding Path=., Source={StaticResource str}}"/>
    </StackPanel>

    其中,引用资源对象 str 作为 TextBlock的Text 的绑定对象,” Path=. " 是可以省略不写的:

    Text="{Binding Source={StaticResource str}}"

    与之对应的 C#代码为:

    string str = "Hello World!";
    this.textBlock1.SetBinding(TextBlock.TextProperty, new Binding(".") { Source = str });

    效果如图:
    在这里插入图片描述


    2.4 —— 没有 Source, 使用 DataContext 作为Binding的源

    DataContext 属性被定义在 FrameworkElement 类里,这个类是WPF控件的基类,意味着所有控件都有这个属性。
    WPF的 UI布局是树形结构,树上的每个结点都是一个控件,所以 ——
    在 UI元素树的每个结点都有 DataContext

    当 Binding只有 Path 而没有 Source时,它会一直向着树的根部,遇到一个控件则查看一下 DataContext。如果一直没有找到,则上下文中不存在该属性。(这种说法并不完全正确,下面会讲到 …

    让我们看一下下面的例子,来感受一下 DataContext:

    1. 创建一个Student类,具有三个属性:
    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }
    1. 创建程序的 UI:
    <StackPanel Background="LightBlue">
    	<StackPanel.DataContext>
    		<local:Student Id="1" Age="20" Name="huameng"/>
            </StackPanel.DataContext>
    	<Grid>
    		<StackPanel>
                    	<TextBox Text="{Binding Id}" Margin="5"/>
                    	<TextBox Text="{Binding Name}" Margin="5"/>
                    	<TextBox Text="{Binding Age}" Margin="5"/>
                	</StackPanel>
            </Grid>
    </StackPanel>

    其中,我们为StackPanel 的DataContext进行赋值,它是 Student对象,并为三个TextBox进行了 Binding,它们会自动去寻找可用的 DataContext 对象

    1. 效果图:

    在这里插入图片描述

    我们前面说过这样一句话:在这里插入图片描述
    我来解释一下这里的问题,其实,这只是WPF给我们的一个错觉,Binding并没有那么智能。
    之所以可以有这样的效果是因为 DataContext是一个 “依赖属性”,当你没有为某个依赖属性赋值时,控件会把自己容器的属性值 “借过来” 当作自己的属性值

    例如看下面的这个例子:

        <Grid>
            <Button x:Name="b" Content="yes" Height="30" Margin="0,-60,0,0" 
            	Click="B_Click"/>
            <Grid>
                <Grid DataContext="6">
                    <Grid>
                        <Button x:Name="btn" Content="OK" Height="30" Margin="0,60,0,0"
                         	Click="Btn_Click"/>
                    </Grid>
                </Grid>
            </Grid>
        </Grid>

    上面的这段代码有两个 Button,放在了不同的层级中,在第一个与第二个 Button之间,有一个 DataContext,我们看看这个例子会发生什么:

    在这里插入图片描述

    我们看到了,点击 OK按钮会显示 DataContext中的数据,但点击 yes按钮却没有任何的反应,
    实际上属性值是沿着 UI元素树向下传递的 ,所以才有这种现象。


    2.5 —— 使用集合对象作为列表控件的 ItemsSource

    2.5.1 ListView控件与后台数据绑定

    我们来实现一下 ListView控件与后台数据绑定的例子,来学习一下ItemsSource 的使用:

    1. XAML 代码如下:
    <StackPanel Background="LightBlue">
            <ListView x:Name="listViewStudents" Height="130" Margin="5">
                <ListView.View>
                    <GridView>
                        <GridViewColumn Header="Id" Width="60" 
    			DisplayMemberBinding="{Binding Id}"/>
                 
                        <GridViewColumn Header="Name" Width="80" 
                            DisplayMemberBinding="{Binding Name}"/>
                 
                        <GridViewColumn Header="Age" Width="60" 
                            DisplayMemberBinding="{Binding Age}"/>
                    </GridView>
                </ListView.View>
            </ListView>
    </StackPanel>

    我们为 ListView控件创建了三列,并将每一列的数据绑定到一个属性中,效果图如下:
    在这里插入图片描述

    1. 实现后台数据,并为 ItemsSouce绑定数据:

    学生类已经之前的例子中写出,此处就不再写了

    ObservableCollection<Student> students = new ObservableCollection<Student>()
    {
    	new Student(){Id = 1, Name="huameng1", Age = 20},
    	new Student(){Id = 2, Name="huameng2", Age = 21},
    	new Student(){Id = 3, Name="huameng3", Age = 22},
    	new Student(){Id = 4, Name="huameng4", Age = 23},
    	new Student(){Id = 5, Name="huameng5", Age = 24},
    	new Student(){Id = 6, Name="huameng6", Age = 25},
    };
    
    this.listViewStudents.ItemsSource = students;

    我创建了一个集合对象,并为这个对象初始化了一些东西,并且这个集合对象赋值给了 listViewStudents 的 ItemsSource 属性。
    这里代码中,并没有之前看到的 Binding,可以会有一些疑问,其实当我们给 ItemsSouce 赋值时,就等同于创建了 Binding。

    细心的朋友可能会发现,我此处用的集合类型不是 List,这是为什么呢?

    因为 ObservbleCollection 这个类,实现了两个接口,分别是:

    • INotifyCollectionChanged
    • INotifyPropertyChanged

    他们会把集合的变化立刻通知显示它的列表控件,改变会立刻显现出来

    1. 效果图如下:
      在这里插入图片描述

    2.5.2 TreeView 绑定 XmlDataProvider

    1. 创建一个 XmlDataProvider对象:
        <Window.Resources>
            <XmlDataProvider x:Key="xdp" XPath="FildSystem/Folder">
                <x:XData>
                    <FildSystem xmlns="">   <!--这句代码必加,不加显示不了结果-->
                        <Folder Name="Books">
                            <Folder Name="programming">
                                <Folder Name="WPF"/>
                                <Folder Name="MFC"/>
                                <Folder Name="Unity"/>
                            </Folder>
                        </Folder>
                        <Folder Name="Tools">
                            <Folder Name="Vs2019"/>
                            <Folder Name="Win10"/>
                            <Folder Name="Phone"/>
                        </Folder>
                    </FildSystem>
                </x:XData>
            </XmlDataProvider>
        </Window.Resources>
    1. 为一个 TreeView对象 绑定 XmlDataProvider:
    <Grid>
    	<TreeView ItemsSource="{Binding Source={StaticResource xdp}}">
                <TreeView.ItemTemplate>
                    <HierarchicalDataTemplate ItemsSource="{Binding XPath=Folder}">
                        <TextBlock Text="{Binding XPath=@Name}"/>
                    </HierarchicalDataTemplate>
                </TreeView.ItemTemplate>
            </TreeView>
    </Grid>

    其中为什么 XPath后面的值有一个加了 @呢?
    很明显,使用@符号加字符串表示的是 XML元素的 Attribute,不加 @表示的是子级元素

    其中有一些模板方面的知识,此处就不讲了,以后我的文章应该会更新

    1. 效果图如下:

    在这里插入图片描述


    2.6 —— 使用 ObjectDataProvider 对象作为 Binding 的Souce

    有的时候,很难保存一个类的所有数据都是使用属性暴露出来,比如我们需要的数据可能是方法的返回值,重新设计一个类成本会高的一比,所以这时候我们就用到了 ObjectDataProvider 来包装Binding源的数据对象了.

    下面们来实现一个例子,输入两个数,能够算出他们的和,将这两个数和他们的和分别绑定一个对象

    1. 设计一个计算器类,实现一个加法的方法:
    class Calculator
    {
    	public string Add(string arg1, string arg2)
            {
                double x = 0;
                double y = 0;
                double z = 0;
    
    	    if (double.TryParse(arg1, out x) && double.TryParse(arg2, out y))
                {
                    z = x + y;
                    return z.ToString();
                }
                
    	    return "Input Error!";
            }
    }
    1. XAML代码如下:
    <StackPanel Background="LightBlue">
            <TextBox x:Name="textBoxArg1" Margin="5"/>
            <TextBox x:Name="textBoxArg2" Margin="5"/>
            <TextBox x:Name="textBoxResult" Margin="5"/>
    </StackPanel>

    效果图如下:
    在这里插入图片描述

    1. MainWindow类构造器中实现 Binding:
    ObjectDataProvider odp = new ObjectDataProvider();
    odp.ObjectInstance = new Calculator();
    odp.MethodName = "Add";
    odp.MethodParameters.Add("0");
    odp.MethodParameters.Add("0");
    
    Binding bindingToArg1 = new Binding("MethodParameters[0]")
    {
    	Source = odp,
    	BindsDirectlyToSource = true,
    	UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
    };
    
    Binding bindingToArg2 = new Binding("MethodParameters[1]")
    {
     	Source = odp,
     	BindsDirectlyToSource = true,
     	UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
    }; 
    
    Binding bindingToResult = new Binding(".") { Source = odp };
    
    this.textBoxArg1.SetBinding(TextBox.TextProperty, bindingToArg1);
    this.textBoxArg2.SetBinding(TextBox.TextProperty, bindingToArg2);
    this.textBoxResult.SetBinding(TextBox.TextProperty, bindingToResult);

    代码解析:

    • 前五行 对Add 方法进行包装(利用ObjectDataProvider)
    • 中间三个Binding 分别将方法的两个参数和结果设置源的路径
    • 最后三行 对 UI元素进行绑定

    可能有朋友会想问 第三个 Binding为什么与前两个Binding有那么大的不同,原因在于:
    在把 ObjectDataProvider对象当作 Binding的 Source来使用时,这个对象本身就代表了数据,所以这里的 Path使用的是 “ . " ,而非其 Data属性。

    1. 动图效果如下:
      在这里插入图片描述

    2.7 —— 使用 Binding的 RelativeSource

    有的时候我们不知道 Source的对象叫什么名字,但我们知道作为 Binding目标的对象在 UI布局上有 相对关系,这时候我们就要使用 Binding的 RelativeSource属性。

    比如下面的这个 XAML代码:

        <Grid x:Name="g1" Background="Red" Margin="10">
            <DockPanel x:Name="d1" Background="Orange" Margin="10">
                <Grid x:Name="g2" Background="Yellow" Margin="10">
                    <DockPanel x:Name="d2" Background="LawnGreen" Margin="10">
                        <TextBox x:Name="textBox1" FontSize="24" Margin="10"/>
                    </DockPanel>
                </Grid>
            </DockPanel>
        </Grid>

    我们如何使 testBox1的 Text特征 绑定到 x:Name 为 g2的呢 ?

    我们可以通过g2相对于 testBox1的层级与类型来确认绑定,如下面代码:

    RelativeSource rs = new RelativeSource(RelativeSourceMode.FindAncestor);
    rs.AncestorLevel = 1;
    rs.AncestorType = typeof(Grid);
    Binding binding = new Binding("Name") { RelativeSource = rs };
    this.textBox1.SetBinding(TextBox.TextProperty, binding);

    我们绑定源为 第一个类型为 Grid的对象的 Name特性

    或者在 XAML 中插入等效代码:

    Text="{Binding RelativeSource={RelativeSource FindAncestor,
    	AncestorType={x:Type Grid}, AncestorLevel=1}, Path=Name}"

    作者:浪子花梦

    展开全文
  • 究竟淘宝是如何做到的,他们是如何在“EBAY(易趣)已经占领大部分中国市场”的局面下,转被动主动?淘宝成功的核心究竟是什么?人和、诚信、细节决定成败!倒立的招式,在何时何地都是非常需要的。落后的时候,...
  •  稻盛和夫两年将日航扭亏为盈,没有别的招数,就两招:一是敬天爱人,尊重员工,员工由被动工作变主动工作;二是阿米巴,用一套会计核算体系植 入人力资源管理,去量化组织中每个团队、每个人操作多少价值。我...
  • 常用的DOS命令

    2018-10-26 20:12:00
    人伤脑 最痛苦的是问题发生后别的非常被动 就一直想如何将这些问题给监控起来 主动一点 ,最近了解一些DOS命令方实现服务监控 今天就和大家一起分享哈: 一、查看windows服务信息 SC命令能与“服务控制器...
  • 2020,我们迎来太多改变。疫情实体经济受到冲击,大批实体店铺由于缺少客流量不得不...疫情时期人与人之间主动被动地隔离,人们被物理性分割为一个个孤岛,通过数字网络才能连接成紧密的整体,使人类社会的运转不至
  •  除了上面两种情况,同学们在实战中还会出现各种需要随机处理的情况,比如主被动语态之间的变换,因为汉语中出现频率较高的是主动语态,而英语中被动语态的出现频率更高,同学们要根据具体情况来随时变换语态。...
  • 6新人面试要由被动变主动,被识的同时也识企业2007-4-25 7教你6个技巧结束职场面试谈话2007-4-25 8面试中可能遇到的问题2007-4-25 9大学生求职择业心理与心理健康2007-3-15 10写自荐信需要注意的几个问题2007-3-9 11...
  • 占领人才高地能企业充满活力,同时也确立了企业的视角和眼界。只有不断优化人才生 态,才能在飞速高效的数字化时代中确立竞争优势。 无论是尖端科技的研究和应用,还是借助高效的运营管理模式实 现业务成长,离不...
  • php高级开发教程说明

    2008-11-27 11:39:22
    像C和P a s c a l这样的语言得如此流行,就是因为它们被广泛应用,并且它们不针对特殊问题, 却提供了能很好地解决普遍问题的工具。 那么P H P是如何适应这一体系的呢?尽管它被称之为一种语言,但P H P并不是一种...
  • │ 高并发编程第一阶段30讲、如何实现一个自己的显式锁Lock精讲下(锁具备超时功能).mp4 │ 高并发编程第一阶段31讲、如何给你的应用程序注入钩子程序,Linux下演示.mp4 │ 高并发编程第一阶段32讲、如何捕获...
  • │ 高并发编程第一阶段30讲、如何实现一个自己的显式锁Lock精讲下(锁具备超时功能).mp4 │ 高并发编程第一阶段31讲、如何给你的应用程序注入钩子程序,Linux下演示.mp4 │ 高并发编程第一阶段32讲、如何捕获...
  • 5.4.3 主动套接字或被动套接字 35 5.5 指明端点地址 35 5.6 类属地址结构 35 5.7 套接字API中的主要系统调用 36 5.7.1 socket调用 37 5.7.2 connect调用 37 5.7.3 send调用 37 5.7.4 recv调用 37 5.7.5 ...

空空如也

空空如也

1
收藏数 20
精华内容 8
热门标签
关键字:

如何让被动变主动