Win10开发:数据绑定

数据绑定并不是Win10的新东西,早在WP7/Win8时代就有了。但是在Win10有新的特性与改变,这在文章的后面讲解。

下面通过几个简单实例说明几种常用的绑定用法。

1、ElementName的使用:

目标:通过Slider的Value值控制Rectangle的Width属性值

实现:

 

[html] view plain copy
 
  1. <Slider x:Name="slider" Minimum="0" Maximum="500" StepFrequency="1"/>  
  2. <Rectangle Width="{Binding Value, ElementName=slider}" Height="10" Fill="Blue"/>  


目标:通过Slider的Value值控制TextBox的Text属性值

 

实现:

 

[html] view plain copy
 
  1. <Slider x:Name="slider" Minimum="0" Maximum="500" StepFrequency="1"/>  
  2. <TextBox Text="{Binding Value, ElementName=slider}" />  


2、绑定方式 Mode

 

上面的例子中通过滑动Slider可以控制TextBox的Text属性,但是却不能改变TextBox的Text值改变Slider的位置。

这时候需要改变Mode的值:

 

[html] view plain copy
 
  1. <TextBox Text="{Binding Value, ElementName=slider, Mode=TwoWay}" />  

 

此时当TextBox失去焦点时,Slider的值将跟着变化

Mode的取值可以是OneTime、OneWay和TwoWay,如果不写的话默认值是OneWay

OneTime :仅当应用程序启动时或 DataContext 进行更改时更新目标属性

OneWay:源更新时,目标也更新

TwoWay:源更新时目标也更新,或者目标更新时同时更新源

 

3、Converter和ConverterParameter

前提:能获取到的是值是某个String值

目标:需要显示一个新的String值的,新的String值是通过修改原始String值得到的

实现:

XAML:

 

[html] view plain copy
 
  1. <TextBox x:Name="textBox" Text="apple is good!"/>  
  2. <TextBlock Text="{Binding ElementName=textBox, Path=Text,Converter={StaticResource  String2NewStringConverter},ConverterParameter=cherish}"/>  



 

其中ConverterParameter是可选的,就是传递给转换器的参数值

String2NewStringConverter是一个资源,在页面中定义:

 

[html] view plain copy
 
  1.  <Page.Resources>  
  2.         <local:StringToNewStringConverter x:Key="String2NewStringConverter" />  
  3. </Page.Resources>  


StringToNewStringConverter是一个实现了IValueConverter接口的类,一般习惯将类名命名为"***Converter":

 

IValueConverter接口要求实现两个函数,Convert和ConvertBack

StringToNewStringConverter的实现:

 

[csharp] view plain copy
 
  1. public class StringToNewStringConverter : IValueConverter  
  2.     {  
  3.         public object Convert(object value, Type targetType, object parameter, string language)  
  4.         {  
  5.             return string.Format("hello windows 10:\nOld String:{0}\nNew String:{1}\nby {2}",value,value.ToString().Replace("apple","microsoft"),parameter);  
  6.         }  
  7.   
  8.   
  9.         public object ConvertBack(object value, Type targetType, object parameter, string language)  
  10.         {  
  11.             return value;  
  12.         }  
  13.     }  


效果图:

 

 

 

4、INotifyPropertyChanged和INotifyCollectionChanged

通过下面的示例可以简单实现集合类数据的绑定。

XAML:

 

[html] view plain copy
 
  1. <ListView x:Name="listView" Grid.Row="0">  
  2.            <ListView.ItemTemplate>  
  3.                <DataTemplate>  
  4.                    <StackPanel Orientation="Horizontal">  
  5.                        <SymbolIcon Symbol="{Binding Symbol}"/>  
  6.                        <TextBlock Text="{Binding Label}" Margin="24,0,0,0" VerticalAlignment="Center"/>  
  7.                    </StackPanel>  
  8.                </DataTemplate>  
  9.            </ListView.ItemTemplate>  
  10. lt;/ListView>  


C#:

 

 

[csharp] view plain copy
 
  1. public sealed partial class MainPage : Page  
  2.     {  
  3.         private List<NavLink> navLinks = new List<NavLink>()  
  4.         {  
  5.             new NavLink() { Label = "People", Symbol =  Symbol.People  },  
  6.             new NavLink() { Label = "Globe", Symbol = Symbol.Globe },  
  7.             new NavLink() { Label = "Message", Symbol = Symbol.Message },  
  8.             new NavLink() { Label = "Mail", Symbol = Symbol.Mail },  
  9.             new NavLink() { Label = "CellPhone", Symbol = Symbol.CellPhone },  
  10.         };  
  11.         public MainPage()  
  12.         {  
  13.             this.InitializeComponent();  
  14.         }  
  15.   
  16.         protected override void OnNavigatedTo(NavigationEventArgs e)  
  17.         {  
  18.             listView.ItemsSource = navLinks;  
  19.             base.OnNavigatedTo(e);  
  20.         }  
  21.     }  
  22.   
  23.     public class NavLink  
  24.     {  
  25.         public string Label { get; set; }  
  26.         public Symbol Symbol { get; set; }  
  27.     }  

 

效果图:


先在有一个需求:通过一个删除按钮实现对页面元素的删除

 

[html] view plain copy
 
  1. <Button Content="删除" Grid.Row="1" VerticalAlignment="Bottom" Width="100" Click="Delete_Click"/>  

 

 

[csharp] view plain copy
 
  1. private void Delete_Click(object sender, RoutedEventArgs e)  
  2. {  
  3.       navLinks.RemoveAt(0);  
  4. }  


增加上面的代码后,点击Button发现页面并没有任何改变。那是因为navLinks是一个List集合,没有实现 INotifyCollectionChanged, INotifyPropertyChanged的接口

解决方案:

将List换成ObservableCollection。因为ObservableCollection实现上面的接口,可以简单的理解为ObservableCollection是实现了 INotifyCollectionChanged, INotifyPropertyChanged接口的List。

结论:

如果工程中自定义的类想要实现属性的改变能让UI界面获得通知,只要实现INotifyPropertyChanged接口即可,自定义的集合类需要实现INotifyCollectionChanged接口。

 

下面是华丽的分割线:

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

接下来的内容是Win10的新特性x:Bind

简单说,x:Bind是x:Binding一定程度上的替代品,据说是80%-90%的情况都可以替代。原来的x:Binding是运行时绑定,而x:Bind是编译时绑定。微软官方的意思就是x:Bind效率高,速度快,方便调试。两个字:好用!

 

1、x:Bind最重要的一个特点就是强类型

使用x:Binding时是不用考虑数据类型的,错了编译器也不会告诉你。没错有时候App莫名其妙的闪退就是它的锅!(其实是你的锅23333)

当使用x:Bind时,如果类型不匹配编译时,就会出错。

 

2、x:Bind默认的DataContext就是Code-Behind

所以无需我们设置上下文:"The data context of x:Bind is the code-behind class"

XAML:

 

[html] view plain copy
 
  1. <TextBlock Text="{x:Bind Text}"/>  


C#:

 

 

[csharp] view plain copy
 
  1. public string Text { get; set; } = "cherish";  

 

 


3、x:DataType

在使用x:Bind+DataTemplate时,必须指定x:DataType,否则编译不成功

 

一个简单的实例:

XAML:

 

[html] view plain copy
 
  1. <ContentControl ContentTemplate="{StaticResource MyDataTemplate}"  Content="{x:Bind ViewModel}" />  


其中MyDataTemplate是一个模板:

 

 

[html] view plain copy
 
  1. <Page.Resources>  
  2.     <DataTemplate x:Key="MyDataTemplate"  
  3.                   x:DataType="local:MainViewModel">  
  4.         <StackPanel Orientation="Horizontal">  
  5.             <SymbolIcon Symbol="{x:Bind Symbol}"/>  
  6.             <TextBlock Text="{x:Bind Label}" Margin="24,0,0,0" VerticalAlignment="Center"/>  
  7.         </StackPanel>  
  8.     </DataTemplate>  
  9. </Page.Resources>  

 

 

C#:

[csharp] view plain copy
 
  1. public sealed partial class MainPage : Page  
  2.   {  
  3.       public MainPage()  
  4.       {  
  5.           this.InitializeComponent();  
  6.       }  
  7.       public MainViewModel ViewModel { get; set; } = new MainViewModel();  
  8.   }  
  9.   
  10.   public class MainViewModel  
  11.   {  
  12.       public string Label { get; set; } = "People";  
  13.   
  14.       public Symbol Symbol { get; set; } = Symbol.People;  
  15.   }  



4、x:Bind默认Mode为OneTime

当绑定的数据项在后台代码中发生改变时,必须调用Bindings.Update()方法进行对UI数据的更新。

 

5、x:Bind绑定事件

XAML:

 

[html] view plain copy
 
  1. <Button x:Name="button" Click="{x:Bind Button_Click}"/>  


C#:

 

 

[csharp] view plain copy
 
  1. public void Button_Click()  
  2. {  
  3.    button.Content = "ButtonClick";  
  4. }  


6、Bindings.StopTracking() 用于中断绑定

 

 

7、x:Bing与ElementName

x:Bing与ElementName不能共存,下面用x:Bind实现1中的“通过Slider的Value值控制Rectangle的Width属性值”

XAML:

 

[html] view plain copy
 
  1. <Slider x:Name="slider" Minimum="0" Maximum="500" StepFrequency="1"/>  
  2. <Rectangle Width="{x:Bind slider.Value,Mode=OneWay}" Height="10" Fill="Blue"/>  

看出来了吗,这里必须指明Mode=OneWay,因为默认的Mode=OneTime

当然也可以给Slider控件添加ValueChanged事件来实现:

 

[csharp] view plain copy
 
  1. private void slider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)  
  2. {  
  3.        Bindings.Update();  
  4. }  

 

没错,看起来似乎变麻烦了。 但是性能得到了提升,这种小例子是看不出什么区别的。性能与便捷性通常是不能兼得的。

 

8、绑定与MVVM

待续...

posted @ 2016-10-02 22:39  天涯海角路  阅读(155)  评论(0)    收藏  举报