Windows Phone 十、数据绑定

数据绑定:是一种 XAML 和后台数据交互的方式(桥梁)
通过后台进行数据绑定
 1     <Grid>
 2         <TextBox
 3             x:Name="txtHello"
 4             Text="{Binding}"
 5             Header="{Binding Path=Value}"/>
 6         <Button 
 7             x:Name="btnHello"
 8             Content="按钮"
 9             Click="btnHello_Click"/>
10     </Grid>
1     public class MainPageData
2     {
3         public string Value { get; set; }
4     }
MainPageData
1         public MainPageData Data { get; set; }
2         private void btnHello_Click(object sender, RoutedEventArgs e)
3         {
4             Data = new MainPageData();
5             Data.Value = DateTime.Now.ToString();
6             //当前页面对象,数据上下文可以被“继承”
7             this.DataContext = Data;
8         }

通过前台进行数据绑定

 1 <Page
 2     x:Class="Myapp.MainPage"
 3     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 4     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 5     xmlns:local="using:Myapp"
 6     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 7     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 8     mc:Ignorable="d"
 9     
10     DataContext="{Binding Data,RelativeSource={RelativeSource Self}}"
11     
12     Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
13     <StackPanel>
14         <TextBox Text="{Binding Text1}"/>
15         <TextBox Text="{Binding Text2}"/>
16     </StackPanel>
17 </Page>
1     public class DataBindingPageData
2     {
3         public string Text1 { get; set; }
4         public string Text2 { get; set; }
5     }
DataBindingPageData
 1     public sealed partial class MainPage : Page
 2     {
 3         //当前页面数据源
 4         public DataBindingPageData Data { get; set; }
 5         public MainPage()
 6         {
 7             //该操作必须在页面初始化之前
 8             Data = new DataBindingPageData();
 9             Data.Text1 = "Hello";
10             Data.Text2 = "World";
11             //界面元素初始化操作
12             this.InitializeComponent();
13             this.NavigationCacheMode = NavigationCacheMode.Required;
14         }
数据绑定的概念
 1 <Page
 2     x:Class="Myapp.MainPage"
 3     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 4     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 5     xmlns:local="using:Myapp"
 6     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 7     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 8     mc:Ignorable="d"
 9     
10     DataContext="{Binding Data,RelativeSource={RelativeSource Self}}"
11     
12     Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
13     <StackPanel>
14         <TextBox Text="{Binding Text1.Value}"/>
15         <TextBox Text="{Binding Text2}"/>
16         
17         <TextBox x:Name="tb1"/>
18     </StackPanel>
19 </Page>
 1 namespace MyApp
 2 {
 3 
 4     /// <summary>
 5     /// 可用于自身或导航至 Frame 内部的空白页。
 6     /// </summary>
 7     public sealed partial class MainPage : Page
 8     {
 9         //当前页面数据源
10         public DataBindingPageData Data { get; set; }
11         public MainPage()
12         {
13             //该操作必须在页面初始化之前
14             Data = new DataBindingPageData();
15             Data.Text1 = new SubData { Value = "Hello" };
16             Data.Text2 = "World";
17             //界面元素初始化操作
18             this.InitializeComponent();
19             this.NavigationCacheMode = NavigationCacheMode.Required;
20         }
21         /// <summary>
22         /// 在此页将要在 Frame 中显示时进行调用。
23         /// </summary>
24         /// <param name="e">描述如何访问此页的事件数据。
25         /// 此参数通常用于配置页。</param>
26         protected override void OnNavigatedTo(NavigationEventArgs e)
27         {
28             #region 数据绑定四个组成部分(目标.依赖属性{绑定}数据源.数据源属性)
29             //绑定桥梁(两头分别是谁)
30             Binding binding = new Binding();
31             //指定数据源和数据源属性
32             binding.Source = Data;
33             binding.Path = new PropertyPath("Text2");
34             //指定绑定的目标依赖属性
35             tb1.SetBinding(TextBox.TextProperty, binding);
36             #endregion
37         }
38     }
39     public class DataBindingPageData
40     {
41         public SubData Text1 { get; set; }
42         public string Text2 { get; set; }
43     }
44     public class SubData
45     {
46         public string Value { get; set; }
47     }
48 }
数据上下文(DataContext)
 1     <Page.Resources>
 2         <SolidColorBrush x:Key="color" Color="AliceBlue"/>
 3         <!--资源中定义数据源对象-->
 4         <local:ResourceBindingPageData
 5             x:Key="myData"
 6             Value="Hello World"/>
 7     </Page.Resources>
 8     <Grid DataContext="{StaticResource myData}">
 9         <TextBox Text="{Binding Value}"/>
10     </Grid>
1     public class ResourceBindingPageData
2     {
3         public string Value { get; set; }
4     }
元素值绑定

数据绑定的数据源不仅仅可以是一个自定义对象,还可以使用 UI 元素对象

就是将一个界面元素对象作为绑定的数据源,轻松实现两个控件之间的交互

基本语法:

Width="{Binding ElementName=sliderDiameter, Path=Value}"

ElementName 就是指定数据源控件的 Name 属性

 1     <StackPanel>
 2         <Slider 
 3             x:Name="slider"
 4             Minimum="50"
 5             Maximum="300"/>
 6         <Ellipse
 7             x:Name="ellipse" 
 8             Width="{Binding ElementName=slider,Path=Value}" 
 9             Height="{Binding ElementName=slider,Path=Value}" 
10             Fill="HotPink"/>
11     </StackPanel>
绑定数值类型转换

当数据源和目标属性类型或格式不相同时,比如URL链接,可以自定义两者之间的转换方式

具体就是实现 IValueConverter 接口

1     <Page.Resources>
2         <local:BookIdToBookUrlConverter x:Key="BookIdToBookUrlConverter"/>
3     </Page.Resources>
4     <Grid>
5         <TextBox Text="{Binding BookId,Converter={StaticResource BookIdToBookUrlConverter}}"/>
6     </Grid>
 1 namespace MyApp
 2 {
 3     /// <summary>
 4     /// 可用于自身或导航至 Frame 内部的空白页。
 5     /// </summary>
 6     public sealed partial class MainPage : Page
 7     {
 8         public ValueConverterPegaData Data { get; set; }
 9         public MainPage()
10         {
11             Data = new ValueConverterPegaData { BookId = 10 };
12             //Data.BookUrl = string.Format("http://www.itcast.cn/book/{0}", Data.BookId);
13             this.InitializeComponent();
14             this.NavigationCacheMode = NavigationCacheMode.Required;
15             this.DataContext = Data;
16         }
17 
18         /// <summary>
19         /// 在此页将要在 Frame 中显示时进行调用。
20         /// </summary>
21         /// <param name="e">描述如何访问此页的事件数据。
22         /// 此参数通常用于配置页。</param>
23         protected override void OnNavigatedTo(NavigationEventArgs e)
24         {
25             // TODO: 准备此处显示的页面。
26 
27             // TODO: 如果您的应用程序包含多个页面,请确保
28             // 通过注册以下事件来处理硬件“后退”按钮:
29             // Windows.Phone.UI.Input.HardwareButtons.BackPressed 事件。
30             // 如果使用由某些模板提供的 NavigationHelper,
31             // 则系统会为您处理该事件。
32         }
33     }
34     public class ValueConverterPegaData
35     {
36         public int BookId { get; set; }
37         public string BookUrl { get; set; }
38     }
39     public class BookIdToBookUrlConverter : IValueConverter
40     {
41         //从原数据转换成目标数据
42         public object Convert(object value, Type targetType, object parameter, string language)
43         {
44             return string.Format("http://www.itcast.cn/book/{0}", value);
45         }
46         //从目标数据转换成原数据
47         public object ConvertBack(object value, Type targetType, object parameter, string language)
48         {
49             return null;
50         }
51     }
52 }

IValueConverter接口实现数值类型转换

 1     <StackPanel>
 2         <StackPanel.Resources>
 3             <local:ValueToColorConverter x:Key="ValueToColorConverter"/>
 4         </StackPanel.Resources>
 5         <Slider 
 6             x:Name="slider"
 7             Minimum="0"
 8             Maximum="255"/>
 9         <Ellipse
10             x:Name="ellipse" 
11             Width="{Binding ElementName=slider,Path=Value}" 
12             Height="{Binding ElementName=slider,Path=Value}" 
13             Fill="{Binding ElementName=slider,Path=Value,Converter={StaticResource ValueToColorConverter}}"/>
14     </StackPanel>
 1     public class ValueToColorConverter : IValueConverter
 2     {
 3         public object Convert(object value, Type targetType, object parameter, string language)
 4         {
 5             var d = (double)value;
 6             var b = (byte)d;
 7             return new SolidColorBrush(Color.FromArgb(255, b, b, b));
 8         }
 9         public object ConvertBack(object value, Type targetType, object parameter, string language)
10         {
11             return null;
12         }
13     }
绑定模式

OneTime:一次绑定,即数据上下文初始化时更新目标属性

OneWay:单向绑定,仅当数据源属性发生变更时更新目标属性

TwoWay:双向绑定,当目标属性发生变更通知数据源变更(同步)

 1     <Grid x:Name="LayoutRoot">
 2 
 3         <Grid.RowDefinitions>
 4             <RowDefinition Height="Auto"/>
 5             <RowDefinition Height="*"/>
 6         </Grid.RowDefinitions>
 7 
 8         <!-- 标题面板 -->
 9         <StackPanel Grid.Row="0" Margin="19,0,0,0">
10             <TextBlock Text="MY APPLICATION" Style="{ThemeResource TitleTextBlockStyle}" Margin="0,12,0,0"/>
11             <TextBlock 
12                 Text="绑定模式" 
13                 Margin="0,-6.5,0,26.5" 
14                 Style="{ThemeResource HeaderTextBlockStyle}" 
15                 CharacterSpacing="{ThemeResource PivotHeaderItemCharacterSpacing}"/>
16         </StackPanel>
17 
18         <!--TODO: 应将内容放入以下网格-->
19         <Grid Grid.Row="1" x:Name="ContentRoot" Margin="19,9.5,19,0">
20             <Grid.RowDefinitions>
21                 <RowDefinition Height="auto"/>
22                 <RowDefinition/>
23                 <RowDefinition/>
24                 <RowDefinition/>
25                 <RowDefinition/>
26             </Grid.RowDefinitions>
27 
28             <Slider
29                 x:Name="slider"
30                 Grid.Row="0"
31                 Value="10"/>
32 
33             <!--默认形式是OneWay-->
34             <TextBox
35                 Grid.Row="1"
36                 Header="Default"
37                 Text="{Binding ElementName=slider, Path=Value}"/>
38 
39             <!--OneTime是在进行数据绑定时同步一次-->
40             <TextBox
41                 Grid.Row="2"
42                 Header="One Time"
43                 Text="{Binding ElementName=slider, Path=Value, Mode=OneTime}"/>
44 
45             <!--OneWay会实时同步数据源变化,但是不会将自身变化同步到数据源-->
46             <TextBox
47                 Grid.Row="3"
48                 Header="One Way"
49                 Text="{Binding ElementName=slider, Path=Value, Mode=OneWay}"/>
50 
51             <!--OneWay会实时同步数据源变化,会将自身变化同步到数据源-->
52             <TextBox
53                 Grid.Row="4"
54                 Header="Two Way"
55                 Text="{Binding ElementName=slider, Path=Value, Mode=TwoWay}"/>
56 
57         </Grid>
58     </Grid>

数据变更通知(一)

使用自定义数据源进行数据绑定时,不管绑定模式是哪一种,都不会造成目标对象实时同步

如果想要实现数据变更实时同步,就必须要让自定义数据类型实现 INotifyPropertyChanged 接口

INotifyPropertyChanged 具有 PropertyChanged 的事件,在数据源被绑定时注册,数据源变更时被触发(需要自己写代码手动触发)

数据变更通知(二)

TwoWay 绑定会在目标和源中的任一个发生更改时同时更新目标和源

此行为的一个例外是,在每次用户击键之后,不会将 TextBox.Text 的更改发送给绑定源

除非将 Binding.UpdateSourceTrigger 设置为 PropertyChanged

默认情况下,仅当 TextBox 失去焦点时才发送更改

INotifyPropertyChanged 封装

1     <StackPanel>
2         <TextBlock/>
3         <TextBox/>
4         <Slider/>
5     </StackPanel>
 1     public class NotifyPropertyChangedPageViewModel : ViewModelBase
 2     {
 3         public string Text1 { get; set; }
 4         private string text2;
 5         public string Text2
 6         {
 7             get { return text2; }
 8             set
 9             {
10                 SetProperty(ref text2, value);
11             }
12         }
13         public double number;
14         public double Number
15         {
16             get { return number; }
17             set
18             {
19                 SetProperty(ref number, value);
20             }
21         }
22         private string hello;
23         public string Hello
24         {
25             get { return hello; }
26             set
27             {
28                 SetProperty(ref hello, value);
29             }
30         }
31     }
32     public abstract class ViewModelBase : NotifyPropertyChanged
33     {
34         protected void SetProperty<TProperty>(ref TProperty current, TProperty value, [CallerMemberName]string propertyName = null)
35         {
36             if (object.Equals(current, value))
37             {
38                 //属性值没有发生变化,减轻应用程序负担
39                 return;
40             }
41             current = value;
42             OnPropertyChanged(propertyName);
43         }
44     }
45     public abstract class NotifyPropertyChanged : INotifyPropertyChanged
46     {
47         /// <summary>
48         /// 当属性发生变化时调用
49         /// </summary>
50         /// <param name="propertyName"></param>
51         protected void OnPropertyChanged(string propertyName)
52         {
53             if (PropertyChanged != null && !string.IsNullOrEmpty(propertyName))
54             {
55                 PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
56             }
57         }
58         public event PropertyChangedEventHandler PropertyChanged;
59     }
集合数据绑定(列表控件元素)

列表控件主要是 ListBox、ListView、GridView 等

为列表控件绑定数据不再是为 DataContext 属性赋值,应该使用列表控件自有的 ItemsSource 属性

当列表数据元素由 ItemsSource 绑定,就不能再动态操作(增删改) Items 属性

ObservableCollection<T>

绑定集合元素和普通绑定一样,界面显示默认不会跟随数据源变化而变化

如果要实现一个动态绑定的列表,通常我们需要用到 ObservableCollection<T> 类型作为数据源集合的类型

1     <Grid>
2         <ListView 
3             x:Name="list" 
4             ItemsSource="{Binding DateTimes}"/>
5         <Button 
6             Content="加载更多"
7             Click="Button_Click"/>
8     </Grid>
 1     public sealed partial class MainPage : Page
 2     {
 3         public MainPageViewModel ViewModel { get; set; }
 4         public MainPage()
 5         {
 6             ViewModel = new MainPageViewModel();
 7             ViewModel.DateTimes = new ObservableCollection<string>();
 8             for (int i = 0; i < 30; i++)
 9             {
10                 ViewModel.DateTimes.Add(string.Format("{0}\t{1}", i, DateTime.Now));
11             }
12             this.InitializeComponent();
13             this.NavigationCacheMode = NavigationCacheMode.Required;
14         }
15         /// <summary>
16         /// 在此页将要在 Frame 中显示时进行调用。
17         /// </summary>
18         /// <param name="e">描述如何访问此页的事件数据。
19         /// 此参数通常用于配置页。</param>
20         protected override void OnNavigatedTo(NavigationEventArgs e)
21         {
22 
23         }
24         private void Button_Click(object sender, RoutedEventArgs e)
25         {
26             //for (int i = 0; i < 20; i++)
27             //{
28             //    //使用数据绑定过后不可以再使用这种形式添加数据
29             //    list.Items.Add(DateTime.Now);
30             //}
31             var max = ViewModel.DateTimes.Count + 20;
32             for (int i = ViewModel.DateTimes.Count - 1; i < max; i++)
33             {
34                 ViewModel.DateTimes.Add(string.Format("{0}\t{1}", i, DateTime.Now));
35             }
36         }
37     }
38     public class MainPageViewModel
39     {
40         //ObservableCollection可以做到数据与界面列表控件实时同步
41         public ObservableCollection<string> DateTimes { get; set; }
42     }
数据展示模版

列表控件中每一个列表项都是又一个默认展示结构的

我们可以通过设置每一个列表控件的 ItemTemplate 属性达到自定义模版的效果

数据展示模版使用

直接为特定 List 控件设置特殊的 DataTemplate

将 DataTemplate 定义到资源当中

 1     <Grid>
 2         <!--<ListView 
 3             x:Name="list" 
 4             ItemsSource="{Binding DateTimes}"/>
 5         <Button 
 6             Content="加载更多"
 7             Click="Button_Click"/>-->
 8         <ListView
 9             x:Name="list"
10             ItemsSource="{Binding Person}">
11             <ListView.ItemTemplate>
12                 <DataTemplate>
13                     <Border BorderBrush="HotPink" BorderThickness="0,0,0,1">
14                         <StackPanel>
15                             <TextBlock FontSize="20">
16                             <Run Text="Id is"/>
17                             <Run Text="{Binding Id}"/>
18                             </TextBlock>
19                             <TextBlock FontSize="32" Text="{Binding Name}"/>
20                         </StackPanel>
21                     </Border>
22                 </DataTemplate>
23             </ListView.ItemTemplate>
24         </ListView>
25     </Grid>
 1     public sealed partial class MainPage : Page
 2     {
 3         public MainPageViewModel ViewModel { get; set; }
 4         public MainPage()
 5         {
 6             ViewModel = new MainPageViewModel();
 7             ViewModel.DateTimes = new ObservableCollection<string>();
 8             for (int i = 0; i < 30; i++)
 9             {
10                 ViewModel.DateTimes.Add(string.Format("{0}\t{1}", i, DateTime.Now));
11             }
12             ViewModel.Person = new ObservableCollection<Person>
13             {
14                 new  Person{Id=1,Name="Hello"},
15                 new  Person{Id=2,Name="World"},
16                 new  Person{Id=3,Name="Hello World"}
17             };
18             this.InitializeComponent();
19             this.NavigationCacheMode = NavigationCacheMode.Required;
20         }
21         /// <summary>
22         /// 在此页将要在 Frame 中显示时进行调用。
23         /// </summary>
24         /// <param name="e">描述如何访问此页的事件数据。
25         /// 此参数通常用于配置页。</param>
26         protected override void OnNavigatedTo(NavigationEventArgs e)
27         {
28 
29         }
30         private void Button_Click(object sender, RoutedEventArgs e)
31         {
32             //for (int i = 0; i < 20; i++)
33             //{
34             //    //使用数据绑定过后不可以再使用这种形式添加数据
35             //    list.Items.Add(DateTime.Now);
36             //}
37             var max = ViewModel.DateTimes.Count + 20;
38             for (int i = ViewModel.DateTimes.Count - 1; i < max; i++)
39             {
40                 ViewModel.DateTimes.Add(string.Format("{0}\t{1}", i, DateTime.Now));
41             }
42         }
43     }
44     public class MainPageViewModel
45     {
46         //ObservableCollection可以做到数据与界面列表控件实时同步
47         public ObservableCollection<string> DateTimes { get; set; }
48         public ObservableCollection<Person> Person { get; set; }
49     }
50     public class Person
51     {
52         public int Id { get; set; }
53         public string Name { get; set; }
54         public override string ToString()
55         {
56             return string.Format("id:{0};name:{1}", Id, Name);
57         }
58     }

 

转载于:https://www.cnblogs.com/includeling/p/4582260.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值