Chinaunix首页 | 论坛 | 博客
  • 博客访问: 6646517
  • 博文数量: 915
  • 博客积分: 17977
  • 博客等级: 上将
  • 技术积分: 8846
  • 用 户 组: 普通用户
  • 注册时间: 2005-08-26 09:59
个人简介

一个好老好老的老程序员了。

文章分类

全部博文(915)

文章存档

2022年(9)

2021年(13)

2020年(10)

2019年(40)

2018年(88)

2017年(130)

2015年(5)

2014年(12)

2013年(41)

2012年(36)

2011年(272)

2010年(1)

2009年(53)

2008年(65)

2007年(47)

2006年(81)

2005年(12)

分类: Android平台

2019-10-27 19:52:50

Source和BindingContext

BindingContext属性实际上是链接源和目标对象的两种方法之一。 您也可以省去BindingContext并在绑定表达式本身中包含对源对象的引用。
BindingSourceCode项目的页面类与OpacityBindingCode中的页面类相同,只是绑定是在两个不涉及BindingContext属性的语句中定义的:


点击(此处)折叠或打开

  1. public class BindingSourceCodePage : ContentPage
  2. {
  3.     public BindingSourceCodePage()
  4.     {
  5.         Label label = new Label
  6.         {
  7.             Text = "Opacity Binding Demo",
  8.             FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)),
  9.             VerticalOptions = LayoutOptions.CenterAndExpand,
  10.             HorizontalOptions = LayoutOptions.Center
  11.         };
  12.         Slider slider = new Slider
  13.         {
  14.             VerticalOptions = LayoutOptions.CenterAndExpand
  15.         };
  16.         // Define Binding object with source object and property.
  17.         Binding binding = new Binding
  18.         {
  19.             Source = slider,
  20.             Path = "Value"
  21.         };
  22.         // Bind the Opacity property of the Label to the source.
  23.         label.SetBinding(Label.OpacityProperty, binding);
  24.         // Construct the page.
  25.         Padding = new Thickness(10, 0);
  26.         Content = new StackLayout
  27.         {
  28.             Children = { label, slider }
  29.         };
  30.     }
  31. }
目标对象和属性仍然在对SetBinding方法的调用中指定:

点击(此处)折叠或打开

  1. label.SetBinding(Label.OpacityProperty, binding);

但是,第二个参数引用一个Binding对象,该对象指定源对象和属性:


点击(此处)折叠或打开

  1. Binding binding = new Binding
  2. {
  3.     Source = slider,
  4.     Path = "Value"
  5. };

这不是实例化和初始化Binding对象的唯一方法。 广泛的Binding构造函数允许指定许多Binding属性。 以下是它如何在BindingSourceCode程序中使用:


点击(此处)折叠或打开

  1. Binding binding = new Binding("Value", BindingMode.Default, null, null, null, slider);
或者您可以使用命名参数来引用滑块对象:

点击(此处)折叠或打开

  1. Binding binding = new Binding("Value", source: slider);

绑定还有一个通用的Create方法,它允许您将Path属性指定为Func对象而不是字符串,这样它就可以更好地抵御错误拼写或属性名称的更改。 但是,此Create方法不包含Source属性的参数,因此您需要单独设置它:

点击(此处)折叠或打开

  1. Binding binding = Binding.Create<Slider>(src => src.Value);
  2. binding.Source = slider;    

BindableObjectExtensions类定义了SetBinding的两个重载,允许您避免显式实例化Binding对象。 但是,这些重载都不包含Source属性,因此它们仅限于使用BindingContext的情况。
BindingSourceXaml程序演示了如何在Binding标记扩展中指定源对象和源属性:

点击(此处)折叠或打开

  1. <ContentPage xmlns=""
  2.              xmlns:x=""
  3.              x:Class="BindingSourceXaml.BindingSourceXamlPage"
  4.              Padding="10, 0">
  5.     <StackLayout>
  6.         <Label Text="Binding Source Demo"
  7.                FontSize="Large"
  8.                VerticalOptions="CenterAndExpand"
  9.                HorizontalOptions="Center"
  10.                Opacity="{Binding Source={x:Reference Name=slider},
  11.                Path=Value}" />
  12.         <Slider x:Name="slider"
  13.                 VerticalOptions="CenterAndExpand" />
  14.     </StackLayout>
  15. </ContentPage>

Binding标记扩展现在有两个参数,其中一个是x:Reference的另一个标记扩展,所以一对花括号嵌套在主花括号中:

点击(此处)折叠或打开

  1. Opacity="{Binding Source={x:Reference Name=slider},
  2.                   Path=Value}" />
为了清晰起见,两个Binding参数在标记扩展中垂直对齐,但这不是必需的。 参数必须用逗号分隔(此处在第一行的末尾),并且大括号内不得出现引号。 您没有在标记扩展中处理XML属性。 这些是标记扩展参数。
您可以通过消除名称参数名称和等号x:引用来简化嵌套标记扩展名,因为Name是ReferenceExtension类的content属性:

点击(此处)折叠或打开

  1. Opacity="{Binding Source={x:Reference slider},
  2.                   Path=Value}" />

但是,您不能同样删除Path参数名称和等号。 尽管BindingExtension将Path定义为其content属性,但只有当该参数是多个参数中的第一个参数时,才能消除参数名称。 你需要像这样切换参数:

点击(此处)折叠或打开

  1. Opacity="{Binding Path=Value,
  2.                   Source={x:Reference slider}}" />

然后你可以消除Path参数名称,也许可以将所有内容移动到一行:

点击(此处)折叠或打开

  1. Opacity="{Binding Value, Source={x:Reference slider}}" />

但是,因为第一个参数缺少一个参数名称而第二个参数有一个参数名称,所以整个表达式看起来有点特殊,并且可能很难在初看时搞定Binding参数。 此外,在Path之前指定Source是有意义的,因为Path指定的特定属性仅对特定类型的对象有意义,并且由Source指定。
在本书中,每当Binding标记扩展包含Source参数时,它将首先出现,然后是Path。 否则,Path将是第一个参数,并且通常会消除Path参数名称。
您可以通过以元素形式表达Binding来完全避免此问题:


点击(此处)折叠或打开

  1. <Label Text="Binding Source Demo"
  2.        FontSize="Large"
  3.        VerticalOptions="CenterAndExpand"
  4.        HorizontalOptions="Center">
  5.     <Label.Opacity>
  6.         <Binding Source="{x:Reference slider}"
  7.                  Path="Value" />
  8.     </Label.Opacity>
  9. </Label>


x:Reference标记扩展仍然存在,但您也可以以元素形式表示:

点击(此处)折叠或打开

  1. <Label Text="Binding Source Demo"
  2.        FontSize="Large"
  3.        VerticalOptions="CenterAndExpand"
  4.        HorizontalOptions="Center">
  5.     <Label.Opacity>
  6.         <Binding Path="Value">
  7.             <Binding.Source>
  8.                 <x:Reference Name="slider" />
  9.             </Binding.Source>
  10.         </Binding>
  11.     </Label.Opacity>
  12. </Label>

您现在已经看到两种方法来指定源对象与目标对象之间的链接:

  • 使用BindingContext引用源对象。
  • 使用Binding类的Source属性或Binding标记扩展。

如果同时指定两者,则Source属性优先于BindingContext。
在你到目前为止看到的例子中,这两种技术几乎可以互换。但是,它们有一些显着的差异。例如,假设您有一个具有两个属性的对象,这两个属性是涉及两个不同源对象的两个不同数据绑定的目标 - 例如,具有绑定到Slider的Opacity属性的Label和绑定到Switch的IsVisible属性。您不能对两个绑定使用BindingContext,因为BindingContext适用于整个目标对象,并且只能指定单个源。必须为这些绑定中的至少一个使用Binding的Source属性。
BindingContext本身由可绑定属性支持。这意味着可以从Binding标记扩展中设置BindingContext。相反,您不能将Binding的Source属性设置为另一个Binding,因为Binding不是从BindableObject派生的,这意味着Source不受可绑定属性的支持,因此不能成为数据绑定的目标。
在BindingSourceXaml标记的此变体中,Label的BindingContext属性设置为包含Source和Path的Binding标记扩展。

点击(此处)折叠或打开

  1. <Label Text="Binding Source Demo"
  2.        FontSize="Large"
  3.        VerticalOptions="CenterAndExpand"
  4.        HorizontalOptions="Center"
  5.        BindingContext="{Binding Source={x:Reference Name=slider},
  6.                                 Path=Value}"
  7.        Opacity="{Binding}" />

这意味着此Label的BindingContext不是前面示例中的滑块对象,而是Double,它是Slider的Value属性。要将Opacity属性绑定到此double,所需的只是一个空的Binding标记扩展,基本上是“对整个数据绑定源使用BindingContext”。
也许BindingContext和Source之间最重要的区别是一个非常特殊的特性,它使得BindingContext不同于所有Xamarin.Forms中的任何其他属性:
绑定上下文通过可视树传播。
换句话说,如果在StackLayout上设置BindingContext,它也适用于该StackLayout的所有子项及其子项。 StackLayout中的数据绑定不必为Binding指定BindingContext或Source参数。它们从StackLayout继承BindingContext。或者StackLayout的子节点可以使用自己的BindingContext设置或绑定中的Source设置覆盖继承的BindingContext。
这个功能非常有用。 假设StackLayout包含一组视觉效果,其数据绑定设置为特定类的各种属性。 设置该StackLayout的BindingContext属性。 然后,StackLayout的子项上的各个数据绑定不需要Source规范或BindingContext设置。 然后,您可以将StackLayout的BindingContext设置为该类的不同实例,以显示每个实例的属性。 您将在前面的章节中看到这种技术的示例和其他数据绑定奇迹,特别是在第19章中。
同时,让我们看一下通过可视树传播BindingContext的更简单的例子。
WebView旨在在您的应用程序中嵌入Web浏览器。或者,您可以将WebView与HtmlWebViewSource类结合使用,以显示一大块HTML,可能保存为PCL中的嵌入式资源。
要显示网页,请使用带有UrlWebViewSource类的WebView指定初始URL。但是,UrlWebViewSource和HtmlWebViewSource都派生自抽象类WebViewSource,并且该类定义了字符串和Uri到其自身的隐式转换,因此您真正需要做的就是将带有Web地址的字符串设置为WebView的Source属性以指示WebView呈现该网页。
WebView还定义了两个名为GoBack和GoForward的方法,这两个方法在内部实现Web浏览器上常见的后退和前进按钮。你的zrogram需要知道什么时候可以启用这些按钮,因此WebView还定义了两个get-only布尔属性,名为CanGoBack和CanGoForward。这两个属性由可绑定属性支持,这意味着对这些属性的任何更改都会导致触发PropertyChanged事件,这进一步意味着它们可以用作数据绑定源来启用和禁用两个按钮。
这是WebViewDemo的XAML文件。请注意,包含两个Button元素的嵌套StackLayout将其BindingContext属性设置为WebView。 StackLayout中的两个Button子项继承了BindingContext,因此按钮可以在其IsEnabled属性上具有非常简单的Binding表达式,这些属性仅引用CanGoBack和CanGoForward属性:



代码隐藏文件需要处理Back和Forward按钮的Clicked事件以及Entry的Completed事件,它允许您输入自己的Web地址:

点击(此处)折叠或打开

  1. public partial class WebViewDemoPage : ContentPage
  2. {
  3.     public WebViewDemoPage()
  4.     {
  5.         InitializeComponent();
  6.     }
  7.     void OnEntryCompleted(object sender, EventArgs args)
  8.     {
  9.         webView.Source = ((Entry)sender).Text;
  10.     }
  11.     void OnGoBackClicked(object sender, EventArgs args)
  12.     {
  13.         webView.GoBack();
  14.     }
  15.     void OnGoForwardClicked(object sender, EventArgs args)
  16.     {
  17.         webView.GoForward();
  18.     }
  19. }

程序启动时您无需输入网址,因为XAML文件已硬编码以转到您喜欢的网站,您可以从那里导航:
阅读(1179) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~