讲讲Windows10(UWP)下的Binding
前言
貌似最近来问我XAML这块的东西的人挺多的。有时候看他们写XAML这块觉着也挺吃力的,所谓基础不牢,地动山摇。XAML这块虽说和HTML一样属于标记语言,但是世界观相对更加庞大一点。
今天讲讲XAML中的Binding。没啥技术含量,全当是快速阅读。
Binding作为MVVM模式的一个相对核心的功能,一直是有争议的。使用数据绑定可以将我们的View和Model解耦,但是如果一旦出现Bug,我们将很难调试,还有一个问题就是数据绑定会带来过大的内存开销。
跟多数的技术一样,都有自己的两面性,具体运用场景如何抉择,应该充分考虑。
作为XAML的一部分,Binding的功能也随着XAML版本的变更着。目前为止,XAML一共有以下几个版本:
- WPF Version
 - Silverlight 3 Version
 - Silverlight 4 Version
 - Windows 8 XAML/Jupiter(Windows Runtime XAML Framework) Version
 
其中WPF版本的Binding功能最强大,但也开销最大。本文中,我们主要讲述最新版本,即__Windows 8 XAML/Jupiter__这个版本的XAML中的Binding。
开始之前
要想讲明白Binding这个东西,我们先要从Binding类的继承层次开始讲。
public class Binding : BindingBase, IBinding, IBinding2
{
    public Binding();
    public IValueConverter Converter { get; set; }
    public System.String ConverterLanguage { get; set; }
    public System.Object ConverterParameter { get; set; }
    public System.String ElementName { get; set; }
    public BindingMode Mode { get; set; }
    public PropertyPath Path { get; set; }
    public RelativeSource RelativeSource { get; set; }
    public System.Object Source { get; set; }
    public System.Object FallbackValue { get; set; }
    public System.Object TargetNullValue { get; set; }
    public UpdateSourceTrigger UpdateSourceTrigger { get; set; }
}
可以看到Binding继承了BindingBase类,还继承了IBinding,IBinding2的接口。我们再分别看下这三个类和接口。首先看下我们的BindingBase。
public class BindingBase : DependencyObject, IBindingBase
{
    public BindingBase();
}
BindingBase又继承了DependencyObject和IBindingBase。DependencyObject这个我们就不多讲了,IBindingBase只是一个空接口。看来BindingBase没有看到太多信息,我们再来看下IBinding和IBinding2。
internal interface IBinding
{
    IValueConverter Converter { get; set; }
    System.String ConverterLanguage { get; set; }
    System.Object ConverterParameter { get; set; }
    System.String ElementName { get; set; }
    BindingMode Mode { get; set; }
    PropertyPath Path { get; set; }
    RelativeSource RelativeSource { get; set; }
    System.Object Source { get; set; }
}
internal interface IBinding2
{
    System.Object FallbackValue { get; set; }
    System.Object TargetNullValue { get; set; }
    UpdateSourceTrigger UpdateSourceTrigger { get; set; }
}
微软设计了一个Binding的基础模型,蕴含了接口分离原则(ISP)的思想,又提供了一个IBindingBase的空接口,如果你想实现自己的Binding模型,可以继承这个接口,这样可以和.NET类库风格统一。
讲讲IBinding
既然我们已经了解了Binding的大概的层次结构,那我们开始一个个讲讲这些都是怎么用的。
IBinding中的Path
Path是我们相对用的比较多的,多数情况下,我们可以这样写
Text="{Binding}"
XAML会取绑定源的ToString的值,所以我们可以重写Override方法来实现我们的需要的绑定。
我们也可以绑定具体的属性,比如:
Text="{Binding Name}"
如果我们绑定了一个集合,那我们也可以尝试这样写:
Text="{Binding MyList[1].Name}"
除了上述比较常用的,我们还有一个叫做ICustomPropertyProvider的接口,当你的类实现了这个接口中的
string GetStringRepresentation()
XAML就会去取这个函数返回的值。
所以总结下我们的Path的绑定方式:
默认情况:
target Text="{Binding}"
source ToString()
//你可以重写ToString方法来改变值
属性绑定:
target Text="{Binding Name}"
source public String Name { get;}
索引器绑定:
target Text="{Binding MyList[1].Name}"
实现ICustomPropertyProvider的绑定:
target Text="{Binding}"
source String GetStringRepresentation()
//实现方法获取值
IBinding中的Mode
Mode一共有三种,OneTime,OneWay,TwoWay。看字面的意思就很容易理解。
//OneTime
Text="{Binding, Mode=OneTime}"
//OneWay
Text="{Binding, Mode=OneWay}"
//TwoWay
Text="{Binding, Mode=TwoWay}"
在OneWay和TwoWay中,如果想要对象的值变更时让绑定目标也变化,需要注意一下两点
- 对于普通的属性,需要类实现INotifyPropertyChanged,并且对象值变化时手动通知变更。
 - 对于依赖属性,当触发SetValue方法后,PropertyChangedCallBack会通知变更,所以无需我们手动操作。
 
在UWP系统中,Mode的默认值为__OneWay__。
IBinding中的RelativeSource
RelativeSource是一种相对关系找数据源的绑定。目前有两种:Self和TemplatedParent
//Self
<TextBlock Text="{Binding Foreground.Color.R, RelativeSource={RelativeSource Mode=Self}}" Foreground="Red"/>
//TemplatedParent
<DataTemplate>
    <Rectangle Fill="Red" Height="30" Width="{Binding Width, RelativeSource={RelativeSource Mode=TemplatedParent}}">
</DataTemplate>
RelativeSource绑定的方式我们常用于控件模板。默认值一般为null。
IBinding中的ElementName
ElementName也是我们最常用的一种绑定方式,使用这个我们需要注意两点:
- 指定的ElementName必须在当前XAML名称范围里。
 - 如果绑定目标位于数据模板或控件模板中,则为模板化父级的XAML名称范围。
 
举个例子:
<UserControl x:Name="Instance" Background="Red">
  <Grid Background="{Binding Background, ElementName=Instance}"/>
</UserControl>
//or
<Page x:Name="Instance">
  <Grid>
    <ItemsControl ItemsSource="{Binding Users}">
      <ItemsControl.ItemTemplate>
        <DataTemplate>
          <Button Command=" {Binding DataContext.TestCommand, ElementName=Instance}"/>
        </DataTemplate>
      </ItemsControl.ItemTemplate>
    </ItemsControl>
   </Grid>
 </Page>
IBinding中的Source
Source也是我们常用的一种方式。
<Page>
  <Page.Resources>
    <SolidColorBrush x:Key="MainBrush" Color="Orange"/>
  </Page.Resources>
  <Grid Background="{Binding Source={StaticResource MainBrush}}"/>
</Page>
//当然我们也可以简写为
<Grid Background="{StaticResource MainBrush}"/>
一般情况下,Source,ElementName和RelativeSource三者是互斥的,指定多余一种的绑定方式会引发异常。
IBinding中的Converter
我们很难保证我们的对象值和我们绑定目标的类型一直,所以转换器可以将类型就行转换。
使用转换器我们要实现IValueConverter接口:
public class BoolVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        bool? result = value as Nullable<bool>;
        if(result == true)
        {
            return Visibility.Visible;
        }
        return Visibility.Collapsed;
    }
    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}
如果你的值需要转换回去,你也可以继续实现ConvertBack方法。
<Page>
  <Page.Resources>
    <local:BoolVisibilityConverter x:Key="BoolVisibilityConverter"/>
  </Page.Resources>
  <Grid>
    <Border Visibility="{Binding Busy, Converter={StaticResource BoolVisibilityConverter}}"/>
  </Grid>
</Page>
IBinding中的ConverterParameter和ConverterLanguage
这两个参数不能绑定,只能指定常量值。
<Border Visibility="{Binding Busy, Converter={StaticResource BoolVisibilityConverter},
  ConverterParameter=One, ConverterLanguage=en-US}"/>
IBinding中的参数基本上覆盖了我们多数的需求。尽管相对于WPF缺少了多值绑定等等,但我们也能够通过自定义一些附加属性来实现这些功能。
IBinding2
IBinding2中的参数就相对使用的比较少了。
IBinding2中的FallbackValue
FallbackValue的用途是:当绑定对象不存在时,我们就使用FallbackValue的值:
<Page>
  <Page.Resources>
    <x:String x:Key="ErrorString">Not Found</x:String>
  </Page.Resources>
  <Grid>
    <TextBlock Text="{Binding Busy, FallbackValue={StaticResource ErrorString}}"/>
  </Grid>
</Page>
IBinding2中的TargetNullValue
TargetNullValue的用途是:当绑定对象为空时,我们就使用TargetNullValue的值:
<Page>
  <Page.Resources>
    <x:String x:Key="ErrorString">Not Found</x:String>
  </Page.Resources>
  <Grid>
    <TextBlock Text="{Binding Busy, TargetNullValue={StaticResource ErrorString}}"/>
  </Grid>
</Page>
IBinding2中的UpdateSourceTrigger
UpdateSourceTrigger的值有三种:Default,PropertyChanged,Explicit。
多数情况下大多数依赖项属性的默认值都为 PropertyChanged。但是Text属性不是。
PropertyChanged的意思是当绑定目标属性更改时,立即更新绑定源。而Explicit是只有UpdateSource方法时才更新绑定源。
举个例子:
<Grid>
    <TextBox x:Name="TitleTextBox" Text="{Binding Title, ElementName=Instance, UpdateSourceTrigger=Explicit, Mode=TwoWay}" />
    <Button Click="Button_Click"/>
</Grid>
private void Button_Click(object sender, RoutedEventArgs e)
{
    var current = this.Title;
    TitleTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
    current = this.Title;
}
有关uwp的Binding就说到这里。谢谢~
参考资料
被误解的MVC和被神化的MVVM
Extensible Application Markup Language
RelativeSource 标记扩展
UpdateSourceTrigger enumeration
个人推荐
讲讲Windows10(UWP)下的Binding的更多相关文章
- Windows10(UWP)下的MEF
		
前言 最近在帮一家知名外企开发Universal Windows Platform的相关应用,开发过程中不由感慨:项目分为两种,一种叫做前人栽树后人乘凉,一种叫做前人挖坑后人遭殃.不多说了,多说又要变 ...
 - Windows10(uwp)开发中的侧滑
		
还是在持续的开发一款Windows10的应用中,除了上篇博客讲讲我在Windows10(uwp)开发中遇到的一些坑,其实还有很多不完善的地方,比如(UIElement.Foreground).(Gra ...
 - 揭秘Windows10 UWP中的httpclient接口[2]
		
阅读目录: 概述 如何选择 System.Net.Http Windows.Web.Http HTTP的常用功能 修改http头部 设置超时 使用身份验证凭据 使用客户端证书 cookie处理 概述 ...
 - Windows10 UWP开发 - 响应式设计
		
Windows10 UWP开发 - 响应式设计 本篇随笔与大家简单讨论一下在开发适配不同分辨率.宽高比的Windows10 Universal App布局时的可行方式与小技巧.经验均从实践中总结, ...
 - Windows10系统下,彻底删除卸载MySQL
		
本文介绍,在Windows10系统下,如何彻底删除卸载MySQL... 1>停止MySQL服务开始->所有应用->Windows管理工具->服务,将MySQL服务停止.2> ...
 - Windows10 VS2015下分别编译libevent 32位和64位库
		
Libevnt 在Windows10 VS2015下分别编译32位和64位库 直接上王道 libevent代码地址: https://github.com/libevent/libevent git ...
 - tensorflow安装过程cpu版-(windows10环境下)---亲试可行方案
		
tensorflow安装过程cpu版-(windows10环境下)---亲试可行方案 一, 前言:本次安装tensorflow是基于Python的,安装Python的过程不做说明 二, 安装环境: ...
 - Windows10环境下使用VisualSVN server搭建SVN服务器
		
参考: Windows10环境下使用VisualSVN server搭建SVN服务器 要搭建个svn用.之前自己的服务器用的乌龟.后来用了这个VisualSVN server. 具体教程见上链接.暂无 ...
 - Windows10系统下安装python2和python3双版本
		
Windows10系统下安装Python3的步骤已经演示过(详见:https://www.cnblogs.com/schut/p/8399195.html),此处不再赘述Python的下载,主要介绍在 ...
 
随机推荐
- WPF触控方面的技术点
			
一.基本的触控事件(原始触控) 二.复杂触控事件(操作)
 - 安装OpenLDAP步骤
			
磨砺技术珠矶,践行数据之道,追求卓越价值 回到上一级页面: PostgreSQL杂记页 回到顶级页面:PostgreSQL索引页 [作者 高健@博客园 luckyjackgao@gmail. ...
 - 12-[数据库]--图形工具Navicat
			
1.Navicat介绍 在生产环境中操作MySQL数据库还是推荐使用命令行工具mysql,但在我们自己开发测试时,可以使用可视化工具Navicat,以图形界面的形式操作MySQL数据库 官网下载:ht ...
 - SQL Server 中SELECT INTO 和 INSERT INTO SELECT 两种表复制语句
			
1.INSERT INTO SELECT语句 语句形式为:Insert into Table2(field1,field2,...) select value1,value2,... from Tab ...
 - VI ORB-SLAM初始化与VINS初始化对比(将vi orb-slam初始化方法移植到vins中)
			
初始化时需要求出的变量:相机和imu外参r t.重力g.尺度s.陀螺仪和加速度计偏置ba bg. 下面对两种算法初始化的详细步骤进行对比: 求陀螺仪偏置bg 求解公式相同,求解方法不同.公式如下,VI ...
 - 【无图慎入】Link Cut Tree 总结
			
link-cut tree 动态树(准确说是维护森林)之一,支持连边,断边,求链上权值和等操作. splay基础:会rotate和splay就行.还要会一点区间反转操作打标记.很基♂础的东西. 有重链 ...
 - linux日志分割、去重、统计
			
一.实例 单条日志模板: 2018-11-08 02:17:22 [Iceberg]process params:IcebergOfferServiceImpl.Params(pk=BF06NA2YE ...
 - css快速入门-引入方式
			
一.概述 HTML是骨架.框架CSS是外表.衣服JS是动作.肌肉 css的主要作用是对元素进行渲染.1.找到要操作的标签(选择器)2.对定位的标签进行操作(属性) 二.CSS引入方式 1.行内式 &l ...
 - javascript  this(上)
			
javascript的this指向的是一个函数运行时动态绑定对象. this的4种常见的指向: 作为对象的方法调用 var obj={ name:"姚小白", getName:fu ...
 - 监控与管理-SpringBoot
			
在微服务架构中,我们将原本庞大的单体系统拆分成多个提供不同服务的应用. 虽然 各个应用的内部逻辑因分解而得以简化,但是由于部署应用的数量成倍增长,使得系统的 维护复杂度大大提升. 对于运维人员来说,随 ...