• 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}	{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}	{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}	{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}	{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     }
  • 相关阅读:
    【转】解决数据库不能更新或数据库或对象为只读
    qt 5 小练习 简易画板
    qt5 基础知识
    qt 5 基础知识 2(控件篇)
    连接sql server、插入数据、从数据库获取时间(C#)
    冒泡排序(C#)
    获取文件的MD5码(C#)
    微信公众平台开发——关于网页签名那些事
    微信公众平台——token验证php版
    浏览器基本工作方法
  • 原文地址:https://www.cnblogs.com/includeling/p/4582260.html
Copyright © 2020-2023  润新知