zoukankan      html  css  js  c++  java
  • 绑定: x:Bind 绑定, x:Bind 绑定之 x:Phase, 使用绑定过程中的一些技巧

    背水一战 Windows 10 之 绑定

    • x:Bind 绑定
    • x:Bind 绑定之 x:Phase
    • 使用绑定过程中的一些技巧



    示例
    1、演示 x:Bind 绑定的相关知识点
    Bind/BindDemo.xaml

    复制代码
    <Page
        x:Class="Windows10.Bind.BindDemo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Windows10.Bind"
        xmlns:common="using:Windows10.Common"
        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="10 0 10 10">
    
                <!--
                    关于 x:Bind 的相关说明:
                    1、Binding 是在运行时(RunTime)绑定;而 x:Bind 是在编译时(BuildTime)绑定(其会在编译时自动生成一些辅助代码,参见对应的 g.cs 代码),所以 x:Bind 的效率要高
                    2、x:Bind 是强类型绑定,类型必须比配;Binding 在绑定时如果类型不必配,会做自动转换
                    3、x:Bind 只具有 Binding 的一部分功能,如下: Path, Mode. FallbackValue, TargetNullValue, Converter, ConverterParameter, ConverterLanguage
                    4、x:Bind 的 Mode 的默认值是 OneTime;Binding 的 Mode 的默认值是 OneWay
                    5、x:Bind 的数据上下文是其所属的 Page 或 UserControl, 不能为 x:Bind 指定其他的数据上下文
                    6、x:Bind 在 DataTemplate 中使用时,必须指定 DataTemplate 的 DataType;而 Binding 则不必
                    7、x:Bind 只能在 xaml 中使用,无法在 CodeBehind 中使用
                    8、x:Bind 支持事件绑定到方法
                    9、仔细看看上面的说明,x:Bind 与 Binding 的大部分不同的本质原因是,他们一个是编译时绑定,一个是运行时绑定
                -->
                
                <!--绑定到属性-->
                <TextBlock Name="textBlock" Text="{x:Bind Path=CurrentEmployee.Name, Mode=OneWay}" Margin="5" />
    
                <!--事件绑定到方法,无参数-->
                <Button Content="修改 CurrentEmployee 的 MyName" Click="{x:Bind EventBindNoArgs}" Margin="5" />
    
                <!--事件绑定到方法,参数与对应的事件的参数相同-->
                <Button Content="修改 CurrentEmployee 的 MyName" Click="{x:Bind EventBindRegularArgs}" Margin="5" />
    
                <!--事件绑定到方法,参数与对应的事件的参数相同,但是其中的事件参数为 object 类型-->
                <Button Content="修改 CurrentEmployee 的 MyName" Click="{x:Bind EventBindBaseArgs}" Margin="5" />
    
                <!--事件绑定到方法,也可以绑定到指定对象中的指定方法-->
                <Button Content="修改 CurrentEmployee 的 MyName" Click="{x:Bind CurrentEmployee.ChangeName}" Margin="5" />
    
                <!--在 DataTemplate 中使用 x:Bind 的注意事项:必须要指定 DataTemplate 的 DataType-->
                <ListView x:Name="listView" ItemsSource="{x:Bind AllEmployees}" Margin="5">
                    <ListView.ItemTemplate>
                        <DataTemplate x:DataType="common:Employee">
                            <TextBlock Text="{x:Bind Name}" />
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
    
                <!--可以与索引器绑定-->
                <TextBlock Name="textBlock2" Text="{x:Bind Path=AllEmployees[0].Name, Mode=OneWay}" Margin="5" />
    
                <!--可以与 Element 绑定-->
                <TextBlock Name="textBlock3" Text="{x:Bind textBlock2.Text, Mode=OneWay}" Margin="5" />
    
            </StackPanel>
        </Grid>
    </Page>
    复制代码

    Bind/BindDemo.xaml.cs

    复制代码
    /*
     * 演示 x:Bind 绑定的相关知识点
     */
    
    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows10.Common;
    
    namespace Windows10.Bind
    {
        // x:Bind 的数据上下文就是它所属的 Page 或 UserControl
        public sealed partial class BindDemo : Page
        {
            public BindDemo()
            {
                this.InitializeComponent();
            }
    
            // 事件绑定到方法,无参数
            private void EventBindNoArgs()
            {
                CurrentEmployee.Name = "wanglei" + new Random().Next(1000, 10000).ToString();
            }
    
            // 事件绑定到方法,参数与对应的事件的参数相同
            private void EventBindRegularArgs(object sender, RoutedEventArgs e)
            {
                CurrentEmployee.Name = "wanglei" + new Random().Next(1000, 10000).ToString();
            }
    
            // 事件绑定到方法,参数与对应的事件的参数相同,但是其中的事件参数为 object 类型
            private void EventBindBaseArgs(object sender, object e)
            {
                CurrentEmployee.Name = "wanglei" + new Random().Next(1000, 10000).ToString();
            }
    
            public Employee CurrentEmployee { get; set; } = new Employee() { Name = "wanglei", Age = 36, IsMale = true };
    
            public ObservableCollection<Employee> AllEmployees { get; set; } = TestData.GetEmployees(5);
        }
    }
    复制代码


    2、演示 x:Bind 绑定之 x:Phase 的相关知识点
    Bind/PhaseDemo.xaml

    复制代码
    <Page
        x:Class="Windows10.Bind.PhaseDemo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Windows10.Bind"
        xmlns:common="using:Windows10.Common"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Page.Resources>
    
            <!--
                关于 x:Phase 的相关说明:
                1、x:Phase 可以实现元素的分阶段显示,用于避免绘制大量数据时的卡顿
                2、ListView 和 GridView 均继承自 ListViewBase
                3、在 windows 8.1 及以后版本中,ListViewBase 是支持 UI 虚拟化的
                4、x:Phase 只适用于 ListViewBase 中的 DataTemplate 里的元素
                5、x:Phase 属于 x:Bind 的一项功能,所以其必须在指定了 x:Bind 的元素中使用才有效
                6、x:Phase 的作用是解决如下问题:当 ListViewBase 滚动时,如果一屏的 item 多,且每个 item 中的 element 也多,那么绘制时会占用大量的资源以至卡顿
                7、在 windows 8.1 及以后版本中,我们可以通过 ContainerContentChanging 事件手动控制列表项的呈现,而 x:Phase 的原理其实就是在编译时自动生成这种手动控制代码(参见对应的 g.cs 代码)
                   关于如何手动控制列表项的呈现,请参见 /Controls/CollectionControl/ListViewBaseDemo/ListViewBaseDemo4.xaml
            -->
            
            <DataTemplate x:Key="PhasedFileTemplate" x:DataType="common:Employee">
                <StackPanel Width="200" Margin="10" Background="Blue">
                    <TextBlock Margin="5" Text="{x:Bind Name}" Foreground="Red" x:Phase="9" />
                    <TextBlock Margin="5" Text="{x:Bind Name}" Foreground="White" />
                    <TextBlock Margin="5" Text="{x:Bind Name}" Foreground="Green" x:Phase="1" />
                    <TextBlock Margin="5" Text="{x:Bind Name}" Foreground="Orange" x:Phase="2" />
                    <TextBlock Margin="5" Text="{x:Bind Name}" Foreground="Orange" x:Phase="2" />
                </StackPanel>
            </DataTemplate>
    
        </Page.Resources>
    
        <Grid Background="Transparent">
    
            <!--
                ShowsScrollingPlaceholders="false" - 不显示占位符
                ContainerContentChanging - 项容器的内容发生变化时触发的事件(在本例中,其用于人为减慢每阶段的显示速度,以便演示)
            
                关于 ShowsScrollingPlaceholders, ContainerContentChanging 的详细说明请参见 ListView, GridView 部分
            -->
            <GridView Name="gridView" Margin="10 0 10 10" ShowsScrollingPlaceholders="false" ContainerContentChanging="gridView_ContainerContentChanging"
                      ItemsSource="{x:Bind AllEmployees}" ItemTemplate="{StaticResource PhasedFileTemplate}" />
    
        </Grid>
    </Page>
    复制代码

    Bind/PhaseDemo.xaml.cs

    复制代码
    /*
     * 演示 x:Bind 绑定之 x:Phase 的相关知识点
     */
    
    using System.Collections.ObjectModel;
    using System.Threading;
    using Windows.UI.Xaml.Controls;
    using Windows10.Common;
    
    namespace Windows10.Bind
    {
        public sealed partial class PhaseDemo : Page
        {
            public PhaseDemo()
            {
                this.InitializeComponent();
            }
    
            // 用于人为减慢每阶段的显示速度,以便演示
            private void gridView_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
            {
                AutoResetEvent h = new AutoResetEvent(false);
                h.WaitOne(1);
    
                uint phase = args.Phase;
                if (phase < 10)
                    args.RegisterUpdateCallback(gridView_ContainerContentChanging);
            }
    
            // 数据源
            public ObservableCollection<Employee> AllEmployees { get; set; } = TestData.GetEmployees(1000);
        }
    }
    复制代码


    3、演示使用绑定过程中的一些技巧
    Bind/Tips.xaml

    复制代码
    <Page
        x:Class="Windows10.Bind.Tips"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Windows10.Bind"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        
        xmlns:common="using:Windows10.Common"
        Background="Red">
    
        <Page.Resources>
            <common:NullableBooleanToBooleanConverter x:Key="NullableBooleanToBooleanConverter" />
        </Page.Resources>
        
        <Grid Background="Transparent">
            <StackPanel Margin="10 0 10 10">
    
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>
                    
                    <!--绑定附加属性,注意要用括号括起来-->
                    <TextBox Name="textBox1" Margin="5" Text="{Binding Path=(Grid.Row), RelativeSource={RelativeSource Self}}" Grid.Row="0" />
    
                    <!--使用绑定时,可以在 Binding 或 x:Bind 后直接加 Path 的值,而不用写“Path=”-->
                    <TextBox Name="textBox2" Margin="5" Text="{Binding (Grid.Row), RelativeSource={RelativeSource Self}}" Grid.Row="1" />
    
                    <!--在 CodeBehind 端绑定附加属性-->
                    <TextBox Name="textBox3" Margin="5" Grid.Row="2" />
                </Grid>
    
                <!--绑定自定义附加属性(在 CodeBehind 端绑定自定义附加属性暂时没有成功)-->
                <TextBox Name="textBox4" Margin="5" local:MyAttachedProperty.SubTitle="custom attached property" Text="{Binding (local:MyAttachedProperty.SubTitle), RelativeSource={RelativeSource Self}}" />
    
                <!--绑定指定对象的指定属性-->
                <TextBox Name="textBox5" Margin="5" Text="{Binding Margin.Top, RelativeSource={RelativeSource Self}}" />
                
                <!--
                    Background 是 Brush 类型
                    SolidColorBrush 继承自 Brush
                    Background.(SolidColorBrush.Color) 的意思就是将 Background 的 Brush 类型转换为 SolidColorBrush 类型并取其 Color 属性
                -->
                <TextBox Name="textBox6" Margin="5" Text="{x:Bind Background.(SolidColorBrush.Color)}" />
    
                <!--
                    x:Bind 没有 ElementName,那如何与其他元素绑定呢,像下面这样即可
                -->
                <TextBox Name="textBox7" Margin="5" Text="{x:Bind textBox6.Text}" />
    
                <!--
                    x:Bind 如何绑定到其他元素的附加属性呢,像下面这样即可
                -->
                <TextBox Name="textBox8" Margin="5" Text="{x:Bind textBox2.(Grid.Row)}" />
    
                <!--
                    x:Bind 如何绑定到其他元素的自定义附加属性呢,像下面这样即可
                -->
                <TextBox Name="textBox9" Margin="5" Text="{x:Bind textBox4.(local:MyAttachedProperty.SubTitle)}" />
    
                <!--
                    在本例中 CurrentEmployee 是 object 类型,要将他转换为 Employee 类型,然后再使用其属性,写法如下
                -->
                <TextBox Name="textBox10" Margin="5" Text="{x:Bind CurrentEmployee.(common:Employee.Name)}" />
    
                <!--
                    Binding 也可以这么写(x:Bind 不支持这么写)
                -->
                <TextBox Name="textBox11" Margin="5">
                    <TextBox.Text>
                        <Binding Path="Text" ElementName="textBox6" />
                    </TextBox.Text>
                </TextBox>
    
                <!--
                    下面的示例用于演示如何绑定到 DataContext 对象的某个属性
                -->
                <TextBox Name="textBox12" DataContext="{x:Bind CurrentEmployee}" Text="{Binding Name}" Margin="5" />
                
                <!--
                    下面的示例用于演示如何直接绑定到 DataContext 对象(而不是绑定 DataContext 对象的某个属性)
                -->
                <TextBox Name="textBox13" DataContext="{x:Bind MyName}" Text="{Binding}" Margin="5" />
    
                <!--
                    Binding 绑定时,如果数据类型不一致,会尝试自动转换,比如此例:bool? 会被自动自动转换为 bool
                -->
                <TextBox Name="textBox14" Text="我是 textBox14" IsReadOnly="{Binding IsChecked, ElementName=chk1}" Margin="5" />
                <CheckBox Name="chk1" Content="textBox14 IsReadOnly" IsChecked="True" Margin="5 0 0 0" />
    
                <!--
                    x:Bind 是编译时的强类型绑定,如果数据类型不一致,不会自动转换,比如此例:要通过 Converter 把 bool? 转换为 bool
                -->
                <TextBox Name="textBox15" Text="我是 textBox15" IsReadOnly="{x:Bind chk2.IsChecked, Mode=TwoWay, Converter={StaticResource NullableBooleanToBooleanConverter}}" Margin="5" />
                <CheckBox Name="chk2" Content="textBox15 IsReadOnly" IsChecked="True" Margin="5 0 0 0" />
    
            </StackPanel>
        </Grid>
    </Page>
    复制代码

    Bind/Tips.xaml.cs

    复制代码
    /*
     * 用于演示使用绑定过程中的一些技巧
     *
     * 在这里插一句:
     * 在 xaml 使用的 {Binding}, {x:Bind}, {StaticResource} 之类的这种带大括号的语法被称为标记扩展(Markup Extension),在 uwp 中无法开发自定义标记扩展(但是在 wpf 中是可以的)
     */
    
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Data;
    using Windows10.Common;
    
    namespace Windows10.Bind
    {
        public sealed partial class Tips : Page
        {
            public Tips()
            {
                this.InitializeComponent();
    
                this.Loaded += Tips_Loaded;
            }
    
            private void Tips_Loaded(object sender, RoutedEventArgs e)
            {
                BindingAttachedProperty();
            }
    
            // 在 CodeBehind 端绑定附加属性
            private void BindingAttachedProperty()
            {
                Binding binding = new Binding()
                {
                    Path = new PropertyPath("(Grid.Row)"), // 注意要有括号,另外在 CodeBehind 端绑定自定义附加属性暂时没有成功
                    Source = textBox3
                };
                BindingOperations.SetBinding(textBox3, TextBox.TextProperty, binding);
            }
    
            // 通过 x:Bind 绑定时,要做转换
            public object CurrentEmployee { get; set; } = new Employee() { Name = "wanglei", Age = 36, IsMale = true };
    
            public string MyName { get; set; } = "webabcd";
        }
    
    
    
        /// <summary>
        /// 用于附加属性的演示
        /// </summary>
        public class MyAttachedProperty
        {
            // 获取附加属性
            public static string GetSubTitle(DependencyObject obj)
            {
                return (string)obj.GetValue(SubTitleProperty);
            }
    
            // 设置附加属性
            public static void SetSubTitle(DependencyObject obj, string value)
            {
                obj.SetValue(SubTitleProperty, value);
            }
    
            // 注册一个附加属性
            public static readonly DependencyProperty SubTitleProperty =
                DependencyProperty.RegisterAttached(
                    "SubTitle", // 附加属性的名称
                    typeof(string), // 附加属性的数据类型
                    typeof(MyAttachedProperty), // 附加属性所属的类
                    new PropertyMetadata("", PropertyMetadataCallback)); // 指定附加属性的默认值,以及值发生改变时所调用的方法
    
            private static void PropertyMetadataCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args)
            {
                object newValue = args.NewValue; // 发生改变之后的值
                object oldValue = args.OldValue; // 发生改变之前的值
            }
        }
    }
  • 相关阅读:
    Could A New Linux Base For Tablets/Smartphones Succeed In 2017?
    使用libhybris,glibc和bionic共存时的TLS冲突的问题
    6 Open Source Mobile OS Alternatives To Android in 2018
    Using MultiROM
    GPU drivers are written by the GPU IP vendors and they only provide Android drivers
    Jolla Brings Wayland Atop Android GPU Drivers
    How to Use Libhybris and Android GPU Libraries with Mer (Linux) on the Cubieboard
    闲聊Libhybris
    【ARM-Linux开发】wayland和weston的介绍
    Wayland and X.org problem : Why not following the Android Solution ?
  • 原文地址:https://www.cnblogs.com/ansen312/p/5913439.html
Copyright © 2011-2022 走看看