重新想象 Windows 8 Store Apps (52) - 绑定: 与 Element Model Indexer
Style RelativeSource 绑定, 以及绑定中的数据转换
作者:webabcd
介绍
重新想象 Windows 8 Store Apps
之 绑定
- 与 Element 绑定
- 与 Model 绑定
- 与 Indexer 绑定
- 对 Style 中的 Setter 进行绑定(绑定静态资源)
- Binding 的一个扩展标记 RelativeSource 的应用
- 绑定中的数据转换
示例
1、演示如何与 Element 绑定,以及 OneTime, OneWay, TwoWay
的区别
Binding/BindingElement.xaml
<Page x:Class="XamlDemo.Binding.BindingElement" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Binding" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="120 0 0 0"> <!-- 本例用于演示如何与 Element 绑定,以及 OneTime, OneWay, TwoWay 的区别 --> <!-- OneTime 方式绑定元素 --> <Slider Name="sliderOneTime" Minimum="1" Maximum="100" Value="10" Width="180" HorizontalAlignment="Left" /> <TextBox Text="{Binding ElementName=sliderOneTime, Path=Value, Mode=OneTime}" Width="150" HorizontalAlignment="Left" /> <!-- OneWay 方式绑定元素(OneWay 是默认方式) --> <Slider Name="sliderOneWay" Minimum="1" Maximum="100" Value="10" Width="180" HorizontalAlignment="Left" Margin="0 50 0 0" /> <TextBox Text="{Binding ElementName=sliderOneWay, Path=Value, Mode=OneWay}" Width="150" HorizontalAlignment="Left" /> <!-- TwoWay 方式绑定元素 --> <Slider Name="sliderTwoWay" Minimum="1" Maximum="100" Value="10" Width="180" HorizontalAlignment="Left" Margin="0 50 0 0" /> <TextBox Text="{Binding ElementName=sliderTwoWay, Path=Value, Mode=TwoWay}" Width="150" HorizontalAlignment="Left" /> </StackPanel> </Grid> </Page>
2、演示如何与 Model 进行双向绑定
Binding/BindingModel.xaml
<Page x:Class="XamlDemo.Binding.BindingModel" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Binding" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="120 0 0 0" Name="root"> <TextBlock Name="lblMsg" FontSize="14.667" /> <TextBox FontSize="14.667" Text="{Binding Path=Name, Mode=TwoWay}" Margin="0 10 10 0" /> <TextBox FontSize="14.667" Text="{Binding Age, Mode=TwoWay}" Margin="0 10 10 0" /> <ToggleSwitch OffContent="女" OnContent="男" Header="性别" Margin="0 10 10 0"> <ToggleSwitch.IsOn> <Binding Path="IsMale" Mode="TwoWay" /> </ToggleSwitch.IsOn> </ToggleSwitch> </StackPanel> </Grid> </Page>
Binding/BindingModel.xaml.cs
/* * 演示如何与 Model 进行双向绑定 */ using System; using System.ComponentModel; using Windows.System.Threading; using Windows.UI.Core; using Windows.UI.Xaml.Controls; using XamlDemo.Model; namespace XamlDemo.Binding { public sealed partial class BindingModel : Page { private Employee _employee; public BindingModel() { this.InitializeComponent(); this.Loaded += BindingModel_Loaded; } void BindingModel_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e) { // 创建一个需要绑定的实体对象(注:Employee 实现了 INotifyPropertyChanged 接口,想要 OneWay 或者 TwoWay 的话必须要实现 INotifyPropertyChanged 接口) _employee = new Employee(); _employee.Name = "webabcd"; _employee.Age = 33; _employee.IsMale = true; // 每 5 秒更新一次数据 ThreadPoolTimer.CreatePeriodicTimer( (timer) => { var ignored = Dispatcher.RunAsync(CoreDispatcherPriority.High, () => { Random random = new Random(); _employee.Age = random.Next(10, 100); _employee.IsMale = random.Next() % 2 == 0 ? true : false; }); }, TimeSpan.FromMilliseconds(5000)); // Employee 对象的属性的值发生变化时触发的事件 _employee.PropertyChanged += _employee_PropertyChanged; root.DataContext = _employee; } // 每次属性的值发生变化时,显示变化后的结果 void _employee_PropertyChanged(object sender, PropertyChangedEventArgs e) { lblMsg.Text = "属性:“" + e.PropertyName + "”的值发生了变化"; lblMsg.Text += Environment.NewLine; lblMsg.Text += string.Format("当前的值为:Name-{0}, Age-{1}, IsMale-{2}", _employee.Name, _employee.Age, _employee.IsMale); } } }
3、演示如何与索引器进行绑定
Binding/BindingIndexer.xaml
<Page x:Class="XamlDemo.Binding.BindingIndexer" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Binding" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="120 0 0 0"> <!--演示如何绑定集合中的某个元素--> <TextBlock Name="textBlock" FontSize="14.667" Text="{Binding Path=[3] }" /> <!--示如何绑定集合中的某个对象的某个属性--> <TextBlock Name="textBlock2" FontSize="14.667" Text="{Binding Path=[5].Name }" Margin="0 10 0 0" /> <!--演示如何绑定 string 类型的索引器--> <TextBlock Name="textBlock3" FontSize="14.667" Text="{Binding Path=[webabcd] }" Margin="0 10 0 0" /> <!--演示如何绑定字典表中指定 key 的数据--> <TextBlock Name="textBlock4" FontSize="14.667" Text="{Binding Path=[hello] }" Margin="0 10 0 0" /> </StackPanel> </Grid> </Page>
Binding/BindingIndexer.xaml.cs
/* * 演示如何与索引器进行绑定 */ using System.Collections.Generic; using Windows.UI.Xaml.Controls; using XamlDemo.Model; namespace XamlDemo.Binding { public sealed partial class BindingIndexer : Page { public BindingIndexer() { this.InitializeComponent(); this.Loaded += BindingIndexer_Loaded; } void BindingIndexer_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e) { // 用于演示如何绑定集合中的某个元素 List<string> list = new List<string>(); for (int i = 0; i < 10; i++) { list.Add("索引:" + i.ToString()); } textBlock.DataContext = list; // 用于演示如何绑定集合中的某个对象的某个属性 textBlock2.DataContext = TestData.GetEmployees(); // 用于演示如何绑定 string 类型的索引器 textBlock3.DataContext = this; // 用于演示如何绑定字典表中指定 key 的数据 Dictionary<string, string> dic = new Dictionary<string, string>(); dic["hello"] = "hello webabcd"; textBlock4.DataContext = dic; } // 自定义一个索引器 public object this[string indexer] { get { return indexer; } } } }
4、演示 Style 中的 Setter
如何做数据绑定(绑定静态资源)
Binding/BindingStyleSetter.xaml
<Page x:Class="XamlDemo.Binding.BindingStyleSetter" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Binding" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="120 0 0 0"> <!-- 演示 Style 中的 Setter 如何做数据绑定 --> <StackPanel.Resources> <!--设置一些资源--> <x:Double x:Key="TextFontSize">24.667</x:Double> <SolidColorBrush x:Key="TextForeground" Color="#00FF00" /> <!--为 Style 的 Setter 的 Value 做数据绑定--> <Style x:Key="MyStyle" TargetType="TextBox"> <Setter Property="FontSize" Value="{Binding Source={StaticResource TextFontSize}}"/> <Setter Property="Foreground" Value="{Binding Source={StaticResource TextForeground}}"/> </Style> </StackPanel.Resources> <!--应用样式--> <TextBox Text="我是TextBox" Style="{StaticResource MyStyle}" /> </StackPanel> </Grid> </Page>
5、演示 Binding 中的一个扩展标记 RelativeSource
的应用
Binding/BindingRelativeSource.xaml
<Page x:Class="XamlDemo.Binding.BindingRelativeSource" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Binding" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="120 0 0 0"> <!-- 演示 Binding 中的一个扩展标记 RelativeSource 的应用,其用于指定关联数据源为 Self 或 TemplatedParent 另外简要说明 TemplateBinding 的应用 --> <StackPanel.Resources> <Style x:Key="MyStyle" TargetType="Button"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <StackPanel> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" /> <!-- TemplateBinding 是一个简单版的 Binding,用于在模板中绑定控件的某个属性 如果设计模板时需要用到双向绑定,则 TemplateBinding 就无能为力了(TemplateBinding 是 OneWay 的) 只能通过 Binding 来做双向绑定,然后通过 RelativeSource={RelativeSource TemplatedParent} 指定数据源来自引用了该 ControlTemplate 的 Control --> <Slider Minimum="1" Maximum="100" Width="{TemplateBinding Width}" Value="{Binding Content, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" /> </StackPanel> </ControlTemplate> </Setter.Value> </Setter> </Style> </StackPanel.Resources> <Button Width="300" Content="10" Style="{StaticResource MyStyle}" /> <!-- RelativeSource={RelativeSource Self} - 指定数据源为自己本身 --> <TextBlock Text="{Binding RelativeSource={RelativeSource Self}, Path=Tag}" Tag="webabcd" FontSize="14.667" Margin="0 10 0 0" /> </StackPanel> </Grid> </Page>
6、演示如何在绑定中做数据转换
Binding/IntegerLetterConverter.cs
/* * 继承 IValueConverter 以实现一个“整数-字母”转换器 */ using System; using Windows.UI.Xaml.Data; namespace XamlDemo.Binding { public sealed class IntegerLetterConverter : IValueConverter { /// <summary> /// 正向转换器。将值从数据源传给绑定目标时,数据绑定引擎会调用此方法 /// </summary> /// <param name="value">转换之前的值</param> /// <param name="targetType">转换之后的类型</param> /// <param name="parameter">转换器所使用的参数(它是通过 Binding 的 ConverterParameter 传递过来的)</param> /// <param name="language">转换器所使用的区域信息(它是通过 Binding 的 ConverterLanguage 传递过来的)</param> /// <returns>转换后的值</returns> public object Convert(object value, Type targetType, object parameter, string language) { if ((double)value == 1) return "a"; else if ((double)value == 2) return "b"; else if ((double)value == 3) return "c"; else return "unknown"; } /// <summary> /// 反向转换器。将值从绑定目标传给数据源时,数据绑定引擎会调用此方法 /// </summary> /// <param name="value">转换之前的值</param> /// <param name="targetType">转换之后的类型</param> /// <param name="parameter">转换器所使用的参数(它是通过 Binding 的 ConverterParameter 传递过来的)</param> /// <param name="language">转换器所使用的区域信息(它是通过 Binding 的 ConverterLanguage 传递过来的)</param> /// <returns>转换后的值</returns> public object ConvertBack(object value, Type targetType, object parameter, string language) { if ((string)value == "a") return 1; else if ((string)value == "b") return 2; else if ((string)value == "c") return 3; else return 1; } } }
Binding/ValueConverter.xaml
<Page x:Class="XamlDemo.Binding.ValueConverter" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Binding" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="120 0 0 0"> <!--配置 IValueConverter 资源--> <StackPanel.Resources> <local:IntegerLetterConverter x:Key="IntegerLetterConverter"/> </StackPanel.Resources> <Slider Name="slider" Minimum="1" Maximum="3" Value="1" Width="180" HorizontalAlignment="Left" /> <TextBox Width="150" HorizontalAlignment="Left" Text="{Binding Value, Mode=TwoWay, ElementName=slider, Converter={StaticResource IntegerLetterConverter}, ConverterParameter=param, ConverterLanguage=zh_cn}" /> <!--注:ConverterParameter 和 ConverterLanguage 不能实现动态的绑定,只能传递静态的参数--> </StackPanel> </Grid> </Page>
OK
[源码下载]
重新想象 Windows 8 Store Apps (52) - 绑定: 与 Element Model Indexer Style RelativeSource 绑定, 以及绑定中的数据转换