silverlight数据绑定模式TwoWay,OneWay,OneTime的研究

asp.net开发中,数据绑定是一个很简单的概念,控件与数据绑定后,控件可以自动把数据按一定的形式显示出来。(当然控件上的值改变后,可以通过提交页面表单,同时后台服务端代码接收新值更新数据)

silverlight中利用控件显示数据这一基本功能当然还保留,只不过因为silverlight应用不需要刷新(也不存在提交表单),所以当控件属性或数据源变化后,在如何相互影响这一块的处理上有所不同。

引用一段silverlight 3 sdk官方的解释:

...

Silverlight 支持以下三种类型的绑定:

创建 OneTime 绑定时,该绑定使用源数据更新目标。

创建 OneWay 绑定时以及每当源数据发生变化时,该绑定使用源数据更新目标。这是默认模式。

当目标和源有一个发生变化时,TwoWay 绑定既更新目标也更新源。或者,您可以禁用自动源更新,只在您选择的时间对源进行更新。

为了能够发生自动目标更新,源对象必须实现 INotifyPropertyChanged 接口,如下一部分所述。

...

简单的说:

OneTime模式下:控件与数据绑定后,能自动显示数据,一旦显示完成后,这二者就没有任何关联了。(即自动解除绑定) OneWay模式下:控件与数据绑定后,除自动显示数据外,显示完成后,控件与数据源仍有单向关联,即如果数据源以后发生了变化,控件上的值也会自动变化. TwoWay模式下:基本与OneWay相同,但是显示完成后,控件与数据源的关联是双向的,即数据源的变化会影响控件上的值,反过来控件上的任何值变化也会影响数据源本身发生变化。

来看一个简单的例子: 

<UserControl x:Class="BindingStudy.MainPage"
    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" 
    mc:Ignorable="d">
    <StackPanel x:Name="LayoutRoot">

        <Rectangle x:Name="rect" Stroke="Black" HorizontalAlignment="Center" VerticalAlignment="Center" Width="{Binding Value, ElementName=silderSelf, Mode=OneTime}"  

Height="80" ></Rectangle>

        <Slider Width="200" Minimum="1" Maximum="200" Value="20" x:Name="silderSelf" Margin="0,10,0,0"></Slider>

        <StackPanel x:Name="sp_Mode" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,10,0,0">
            <RadioButton Content="OneTime" x:Name="rboMode_OneTime" GroupName="bindMode" IsChecked="True" Checked="rboMode_OneTime_Checked"></RadioButton>
            <RadioButton Content="OneWay" x:Name="rboMode_OneWay" GroupName="bindMode" Margin="10,0,0,0" Checked="rboMode_OneWay_Checked" ></RadioButton>
            <RadioButton Content="TwoWay" x:Name="rboMode_TwoWay" GroupName="bindMode" Margin="10,0,0,0" Checked="rboMode_TwoWay_Checked" ></RadioButton>
        </StackPanel>
        
        <StackPanel x:Name="sp_Button" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,10,0,0">
            <Button x:Name="btnWidthAdd" Content="矩形宽度+5px" Click="btnWidthAdd_Click"></Button>
            <Button x:Name="btnWidthSub" Content="矩形宽度-5px" Margin="10,0,0,0" Click="btnWidthSub_Click"></Button>
        </StackPanel>
    </StackPanel>
</UserControl>

解释一下:

最上面是一个矩形rect,下面是一个滑块拖动条silderSelf,其它的先不管,矩形的Width属性注意一下:

Width="{Binding Value, ElementName=silderSelf, Mode=OneTime}"

这里将矩形的宽度与滑块的Value值做了绑定(即矩形的宽度即为滑动条的值),模式为OneTime(即绑定完成后,二者再无任何关联)

tips:上面提到的绑定语法不用死记硬背,在Blend里用图形界面即可设置

选中矩形对象,点击属性面板Width右边的小黄点,弹出菜单中选择"Data Binding..."

设置绑定

运行效果: 

先不用急着关注其它东西,我们注意到矩形的宽度自动变成20了,即silder的value初始值,然后我们拖动滑块试下,矩形的宽度没有变化!也就映证了OneTime模式下,一旦绑定完成(数据显示结束),控件与数据源就再无任何瓜葛,大家各走各的路,各过各的桥。 为了测试另外二种模式,我在后台加了一些代码 :

using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace BindingStudy
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }

        private void rboMode_OneTime_Checked(object sender, RoutedEventArgs e)
        {
            if (rect != null)
            {
                Binding bindwidth = new Binding("Value");
                bindwidth.Mode = BindingMode.OneTime;
                this.rect.SetBinding(UserControl.WidthProperty, bindwidth);
                this.rect.DataContext = silderSelf;
            }
        }

        private void rboMode_OneWay_Checked(object sender, RoutedEventArgs e)
        {
            if (rect != null)
            {
                Binding bindwidth = new Binding("Value");
                bindwidth.Mode = BindingMode.OneWay;
                this.rect.SetBinding(UserControl.WidthProperty, bindwidth);
                this.rect.DataContext = silderSelf;
            }
        }

        private void rboMode_TwoWay_Checked(object sender, RoutedEventArgs e)
        {
            if (rect != null)
            {
                Binding bindwidth = new Binding("Value");
                bindwidth.Mode = BindingMode.TwoWay;
                this.rect.SetBinding(UserControl.WidthProperty, bindwidth);
                this.rect.DataContext = silderSelf;
            }
        }

       
        private void btnWidthAdd_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            if (rect != null) 
            {
                rect.Width += 5;
            }
        }

        private void btnWidthSub_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            if (rect != null)
            {
                rect.Width -= 5;
            }
        }
    }
}

代码不复杂,基本功能就是让绑定模式可以自由切换,相信大家一看就明白 这回我们来测试一下OneWay模式,运行后选择OneWay模式,然后再手动拖动滑块,会发现矩形的宽度随着滑块的值不断变化,即OneWay模式下,数据源的变化会自动反应在绑定的目标控件上,继续,我们点击最下面的二个按钮,改变矩形的宽度,发现滑块不会自己移动,这说明了OneWay模式下控件的属性变化,不会反过来影响数据源本身。

最后切换到TwoWay模式,与OneWay模式的不同之外在于,如果我们点击最下面的按钮,改变矩形的宽度,会发现滑块自己移动了,移动后的值即为矩形的宽度,结论:TwoWay模式下,控件与数据源任何一方的变化都会影响对另一方。(个人感觉这个功能很NB,如果我们自己实现的话,不知道要写多少行代码!)

当然,实际开发中,我们的数据源通常不会是某一个现成控件的属性,多半是xml/数据库等对应的实体类,这里要注意的是,如果控件与自定义类绑定,自定义类必须实现INotifyPropertyChanged接口,参考下面的代码:

public class Test : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private double _width;

        public double Width
        {
            set
            {
                _width = value;
                if (PropertyChanged != null) 
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("Width"));
                }
            }

            get
            {
                return _width;
            }
        }
    }

转载请注明来自菩提树下的杨过

最后给出文中源码下载:http://files.cnblogs.com/yjmyzz/BindingStudy.rar

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Nian糕的私人厨房

WeChat 文章列表页面(二)

本次的系列博文的知识点讲解和代码,主要是来自于 七月老师 的书籍《微信小程序开发:入门与实践》,由个人总结并编写,关于更多微信小程序开发中的各项技能,以及常见问...

1694
来自专栏拂晓风起

HTML5动画软件工具编辑器 HTML5动画分类 工具推荐

1963
来自专栏飞雪无情的博客

Android设计应用图标不用愁---Asset Studio Integration来帮你

Android Asset StudioWeb版是一个非常好用的Andrid图标资源设计工具,它是由RomanNurik开发的。现在我们已经在ADT14里支持同...

1155
来自专栏对角另一面

读Zepto源码之Fx模块

fx 模块为利用 CSS3 的过渡和动画的属性为 Zepto 提供了动画的功能,在 fx 模块中,只做了事件和样式浏览器前缀的补全,没有做太多的兼容。对于不支持...

3370
来自专栏V站

Note丨记41条Web程序员日常使用的代码!

2228
来自专栏LinXunFeng的专栏

iOS - Swift UIButton中ImageView的animationImages动画执行完毕后,图标变暗

1613
来自专栏极乐技术社区

微信小程序那点事:特性总结

一、微信小程序运行环境 1、完全封闭的环境不等于浏览器环境 2、WXML/WXSS/JS格式 3、WXML 不等于 HTML 4、WX...

2226
来自专栏郭霖

Android最佳性能实践(四)——布局优化技巧

在前面几篇文章当中,我们学习了如何通过合理管理内存,以及高性能编码技巧的方式来提升应用程序的性能。然而实际上界面布局也会对应用程序的性能产生比较大的影响,如果布...

2428
来自专栏陈仁松博客

UWP基础教程 - AuotmationProperties.Name

作为Windows10 UWP开发,大家应该会在很多示例DEMO里面看到AuotmationProperties.Name这个属性吧 <Button Autom...

3565
来自专栏Bug生活2048

.net core下对于Excel的一些操作及使用

对于后台相关的管理系统,Excel导出是基本的功能,下面就简单说下实现该功能的代码实现吧

1692

扫码关注云+社区

领取腾讯云代金券