<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}" x:Name="gridBook" > <Grid.RowDefinitions > <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <StackPanel Grid.Row="0" Orientation="Horizontal"> <TextBlock Text="书名:" FontSize="96" VerticalAlignment="Center" Margin="30,0,0,0"/> <TextBlock x:Name="txtBlockName" Foreground="Red" FontSize="96" Text="{Binding Name}" VerticalAlignment="Center"/> </StackPanel> <StackPanel Grid.Row="1" Orientation="Horizontal"> <TextBlock Text="价格:" FontSize="96" VerticalAlignment="Center" Margin="30,0,0,0"/> <TextBlock x:Name="txtBlockPrice" Foreground="Red" FontSize="96" Text="{Binding Price}" VerticalAlignment="Center"/> </StackPanel> <StackPanel Grid.Row="2" Orientation="Horizontal"> <TextBlock Text="类型:" FontSize="96" VerticalAlignment="Center" Margin="30,0,0,0"/> <TextBlock x:Name="txtBlockType" Foreground="Red" FontSize="96" Text="{Binding Type}" VerticalAlignment="Center"/> </StackPanel> </Grid>
namespace App1 { /// <summary> /// An empty page that can be used on its own or navigated to within a Frame. /// </summary> public sealed partial class MainPage : Page { public MainPage() { this.InitializeComponent(); } /// <summary> /// Invoked when this page is about to be displayed in a Frame. /// </summary> /// <param name="e">Event data that describes how this page was reached. The Parameter /// property is typically used to configure the page.</param> protected override void OnNavigatedTo(NavigationEventArgs e) { var book = new Book("XAML Primer", 24.4, "移动开发"); gridBook.DataContext = book; } } public class Book { public string Name { get; set; } public double Price { get; set; } public string Type { get; set; } public Book(string name, double price, string type) { Name = name; Price = price; Type = type; } } }
运行结果为:
在XAML中,先给Grid起名字,然后在里面定义了三行,每一行里面分别定义了一个StackPanel,用来存放数据标签和数据内容。
数据绑定时,使用{binding perperty}这样的方式绑定数据,由于Book里面有三个成员变量,且分别为Name,Price和Type,所以这里的Property分别设为这三个值即可。
在代码中,使用DataContext来指定数据源,对于每个控件可以使用这个来绑定,因此可以使用代码:
txtName.DataContext = book; txtPrice.DataContext = book; txtType.DataContext = book;
来指定数据源,写起来实际是很不方便的,因为如果控件多了,每个都要这么指定那岂不是很繁琐,所以这里可以采用一点小技巧使用一条语句即可。根据数据绑定里面的一个规则:子类继承父类的数据源,我们可以很方便地写出完成这个功能的代码,因为三个控件都在一个Grid里面,所以在这里直接把Grid的数据源指定为book即可,那么其所有的子控件的默认数据源就都是book了。
数据绑定有三种模式:OneTime,OneWay和TwoWay
1)OnewTime:绑定的数据源发生了变化,绑定的目标控件的UI也不会发生改变,可以用来给出任意时刻的数据库的快照
2)OneWay:数据源发生了改变,UI也会跟着更新,但是UI更新了,数据源不会更新,这个是单向的。
3)TwoWay:数据源和UI控件任何一个修改了,另外一个会跟着发生改变。
使用的时候,指定数据源的格式为:
<Text="{Binding Name, Mode=TwoWay}” />一般而言,TextBlock使用OneWay,而TextBox使用TwoWay。需要注意的是,上面所说的OneWay和TwoWa,y如果你直接指定模式,然后绑定数据,当数据源发生变化的时候,你会发现UI界面上所绑定的控件并不会随之而变化,难道我忘记了什么?答案是,当你使用OneWay和TwoWay的时候,如果你希望你的界面能够跟着数据源实时变化,那么你需要做一些“额外”做的工作了。1)类首先必须继承INotifyPropertyChanged类;
2)声明对象:PropertyChangedEventHandler PropertyChanged;在更改属性时引发该事件。
3)数据源设置调用事件响应函数,如:
private int _Age; public int Age { get { return this._Age; } set { this._Age = value; notifyPropertyChanged(); } }4)实现响应函数,触发NotifyPropertyChanged事件,例子如:private void NotifyPropertyChanged(String info) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(info)); } }
在数据绑定过程中,数据往往并不是直接兼容的,所以这个时候就需要使用到数据转换了,方法是构建一个实现了IValueConverter类的类,在这类类里面实现Convert函数和可选的ConvertBack函数.
XAML文件:
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> <StackPanel HorizontalAlignment="Left"> <ComboBox x:Name="comboBox" ItemsSource="{Binding}" Foreground="Black" FontSize="30" Height="50" Width="550"> <ComboBox.ItemTemplate> <DataTemplate> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"></ColumnDefinition> <ColumnDefinition Width="*"></ColumnDefinition> <ColumnDefinition Width="*"></ColumnDefinition> <ColumnDefinition Width="*"></ColumnDefinition> </Grid.ColumnDefinitions> <TextBox Text="Name:" Grid.Column="0"/> <TextBox Text="{Binding Name}" Grid.Column="1"/> <TextBox Text="Title:" Grid.Column="2"/> <TextBox Text="{Binding Title}" Grid.Column="3"/> </Grid> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox> <StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <Button x:Name="btnChangeData" Grid.Column="0" Content="ClickMeChangeName" HorizontalAlignment="Left" FontSize="48" Click="btnChangeData_Click"></Button> <Button x:Name="btnGetData" Grid.Column="1" Content="ClickMeGetName" HorizontalAlignment="Right" FontSize="48" Click="btnGetData_Click"></Button> </Grid> </StackPanel> <TextBox x:Name="txtBindingData" Text="{Binding Name, Mode=TwoWay}" FontSize="68"></TextBox> </StackPanel> </Grid>C#源代码:using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.IO; using System.Linq; using Windows.Foundation; using Windows.Foundation.Collections; using Windows.UI.Popups; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls.Primitives; using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 namespace BindingDemo { /// <summary> /// An empty page that can be used on its own or navigated to within a Frame. /// </summary> public sealed partial class MainPage : Page { private Employee employee = new Employee {Name="good", Title="hust"}; public MainPage() { this.InitializeComponent(); } /// <summary> /// Invoked when this page is about to be displayed in a Frame. /// </summary> /// <param name="e">Event data that describes how this page was reached. The Parameter /// property is typically used to configure the page.</param> protected override void OnNavigatedTo(NavigationEventArgs e) { comboBox.ItemsSource = Employee.GetEmployees(); txtBindingData.DataContext = employee; } private void btnChangeData_Click(object sender, RoutedEventArgs e) { employee.Name = new DateTime().ToString("yyyy-MM-dd"); } private async void btnGetData_Click(object sender, RoutedEventArgs e) { MessageDialog dlg = new MessageDialog(employee.Name, "btnGetData_Click"); dlg.Commands.Add(new UICommand("Ok")); await dlg.ShowAsync(); } } public class Employee : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private string _name; public string Name { get { return _name; } set { _name = value; RaisePropertyChanged(); } } private string _title; public string Title { get { return _title; } set { _title = value; RaisePropertyChanged(); } } private void RaisePropertyChanged(string caller = "" ) { if (PropertyChanged != null ) { PropertyChanged( this, new PropertyChangedEventArgs( caller ) ); } } public static ObservableCollection<Employee> GetEmployees() { var employees = new ObservableCollection<Employee>(); employees.Add( new Employee() { Name = "Washington", Title = "President 1" } ); employees.Add( new Employee() { Name = "Adams", Title = "President 2" } ); employees.Add( new Employee() { Name = "Jefferson", Title = "President 3" } ); employees.Add( new Employee() { Name = "Madison", Title = "President 4" } ); employees.Add( new Employee() { Name = "Monroe", Title = "President 5" } ); return employees; } } }