WPF-绑定
一个绑定常常由绑定源、路径、绑定目标及目标属性四部分组成。绑定源用来标示源属性所存在的类型实例,路径用来标示需要绑定到的处于绑定源之上的源属性,绑定目标标示将接受相应更改的属性所在的实例,目标属性则用来标示接受绑定运行值的目标,而转换器则在源属性和目标属性不能直接赋值时执行转化工作。这四部分组成之间的联动方式为:绑定源发出属性更新的通知,从而驱动绑定执行。其中源属性将作为绑定的输入,而绑定的输出则被赋予目标属性。如果绑定声明中标明了转换器,那么转换器将被执行,从而将源属性转化为合适的目标属性。[引用自:WPF - 绑定及惯用法(一)]
一个简单易懂的数据绑定的例子:
<Window x:Class="binding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:binding"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Canvas>
<ScrollBar Height="24" Name="scrollBar1" Width="237" Orientation="Horizontal" Canvas.Left="107" Canvas.Top="53" Minimum="1" Maximum="100" SmallChange="1" />
<Label Canvas.Left="41" Canvas.Top="121" Content="OneWay" Height="28" Name="label1" />
<TextBox Canvas.Left="165" Canvas.Top="121" Height="23"
Text="{Binding ElementName=scrollBar1, Path=Value, Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"
Name="textBox1" Width="120" />
<Label Canvas.Left="41" Canvas.Top="160" Content="OneWayToSource" Height="28" Name="label2" />
<TextBox Canvas.Left="165" Canvas.Top="160" Height="23"
Text="{Binding ElementName=scrollBar1, Path=Value, Mode=OneWayToSource,UpdateSourceTrigger=PropertyChanged}"
Name="textBox2" Width="120" />
<Label Canvas.Left="41" Canvas.Top="202" Content="TwoWay" Height="28" Name="label3" />
<TextBox Canvas.Left="165" Canvas.Top="202" Height="23"
Text="{Binding ElementName=scrollBar1, Path=Value, Mode=TwoWay}"
Name="textBox3" Width="120" />
<Label Canvas.Left="41" Canvas.Top="231" Content="OneTime" Height="28" Name="label4" />
<TextBox Canvas.Left="165" Canvas.Top="231" Height="23"
Text="{Binding ElementName=scrollBar1, Path=Value, Mode=OneTime}"
Name="textBox4" Width="120" />
</Canvas>
</Window>
不用写一行代码,即可实现数据绑定。
命令
谈到数据绑定,就不得不顺便提一下命令了,WPF中的命令是实现ICommand
接口的类,而谈到命令,便不得不谈谈命令和事件的关系,前边做事件相关的程序那么久了,包括自定义事件,.NET
平台提供的事件等。事件驱动和命令的最大区别在于,事件不具有约束力,命令是具有约束力的,任何命令目标收到命令源发起的命令必须响应。
下面的这个例子可以很好地解释命令中的几大要素:命令源、命令目标、命令绑定和命令。
一组形象的比喻,分别对应:长官、轰炸目标、侦察兵、“发射”,如下:
<!--布局文件-->
<Window x:Class="binding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:binding"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid x:Name="grid">
<TextBox HorizontalAlignment="Left" Height="36" Margin="10,65,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="160" x:Name="textbox"/>
<Button Content="us" HorizontalAlignment="Left" Height="36" Margin="206,26,0,0" VerticalAlignment="Top" Width="73" x:Name="button1" CommandParameter="us"/>
<Button Content="enemy" HorizontalAlignment="Left" Height="36" Margin="206,83,0,0" VerticalAlignment="Top" Width="73" x:Name="button2" CommandParameter="enemy"/>
</Grid>
</Window>
//后台代码
using System.Windows;
using System.Windows.Input;
namespace binding
{
public partial class MainWindow : Window
{
private RoutedCommand GO = new RoutedCommand("Go", typeof(MainWindow));//与具体业务逻辑无关的命令类
public MainWindow()
{
InitializeComponent();
this.button1.Command = this.GO;
this.button2.Command = this.GO;
this.button1.CommandTarget = this.textbox;
this.button2.CommandTarget = this.textbox;
//命令绑定
CommandBinding cb = new CommandBinding();
cb.Command = this.GO;
//把命令安置在外围控件上
this.grid.CommandBindings.Add(cb);
cb.CanExecute += cb_CanExecute;
cb.Executed += cb_Executed;
}
void cb_Executed(object sender, ExecutedRoutedEventArgs e)
{
if (e.Parameter.ToString() == "我方")
{
this.textbox.Text = "我方!!!";
}
if (e.Parameter.ToString() == "敌方")
{
this.textbox.Text = "敌方";
}
}
void cb_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
if (string.IsNullOrEmpty(this.textbox.Text))
{
e.CanExecute = true;
}
else
{
e.CanExecute = false;
}
//当消息处理结束后,避免将该附加事件沿着UI树继续向上传递
e.Handled = true;
}
}
}
这里需要注意的问题是,CommandBinding
一定要设置在命令目标的外围控件上,不然无法捕捉到CanExecute
和Executed
等路由事件。
所谓路由事件,单起一章来谈,此处略过。
命令库
WPF类库中包含一些便捷的命令库,上边的这个命令是我们自己写的。而命令库中的命令即静态类的静态只读属性,我们也可以自己写具有特定功能的命令类。
命令与数据绑定
一个控件只有一个Command
属性,要想一个控件在不同条件下响应不同的事件,可以考虑使用绑定。
需求分析及方案编制
所谓需求,就是想要什么,想实现什么样的功能。人们为了要解决现实社会和生活中的各种问题,所以会求助于软件。然而,非专业的需求者往往不能完整地陈述他们真实的需求,这个时候就需要我们去引导。当然,有的需求是我们自己提给自己的,比如我们开发一款硬件设备,这个时候的驱动程序自然是我们自己完成,这时候不能空想驱动的功能要怎样,还需要结合已有的驱动是怎么样的,软件的代码、架构、所以来的平台以及长期的演化,会有哪些技术层面的需求。而这便涉及到了所谓的设计需求。我们如何通过软件、驱动的使用友好性提高我们产品的竞争力。不同的软件,关注点不一样,总的来说,可以将需求分为:
功能性需求——要求产品必须实现某些功能;
开发过程需求——设计文档的编写,时间节点的把握;
服务质量需求——即可靠性分析和安全性分析,最基本的就是不能让程序跑着跑着崩了,在此之上,我们有一定的响应时间要求,操作便捷性要求等;
综合需求——软件不单单是一款软件,我们更多的是和社会生活以及硬件配套使用的,所以要综合不同系统达到预期效果。
方案编制方面,我们可以参考《GJB438B-2009 军用软件开发文档通用要求.pdf》中的软件研制任务书一节,外加一些特殊要求即可。
这周写的设备管理软件的需求文档,还有很多不足的地方,目前来讲,需求文档的目录如下:
文档说明
1.1.编写目的
1.2.编写依据
1.3.使用部门
1.4.修订记录
1.5.术语和缩略词软件概要
2.1.软件总体描述
2.2.软件设计约束及有关说明
2.2.1.开发及测试环境
2.2.2.编程语言
2.2.3.运行环境
2.2.3.1.硬件环境
2.2.3.2.软件环境
2.3.使用者特点详细需求
3.1.功能
3.1.1.产品管理
3.1.1.1.需求说明
3.1.1.2.面向角色
3.1.1.3.实现功能
3.1.1.4.功能说明
3.1.2.产品使用(服务)
3.1.2.1.需求说明
3.1.2.2.面向角色
3.1.2.3.实现功能
3.1.2.4.功能说明
3.2.软件执行过程概述
3.3.性能
3.3.1.时间特性要求
3.3.2.灵活性要求
3.4.输入/输出
3.5.接口
3.5.1.外部接口
3.5.2.软件接口
3.6.关键性要求
3.6.1.可靠性
3.6.1.1.软件运行故障
3.6.1.2.软件使用故障
3.6.2.安全性质量控制要求
4.1.标准
4.2.配置管理
4.3.测试要求验收和交付
5.1.软件的验收准则
5.2.软件的交付形式、数量、装载媒体及交付日期
5.3.应交付的文档清单
5.4.软件的版权保护
5.4.1.版权声明
5.4.2.商标声明
5.4.3.相关法律软件保障要求
进度记录
7.1.产品开发计划
7.2.功能时间分配表
接下来不断完善吧~