背水一战 Windows 10 (20) - 绑定: DataContextChanged, UpdateSourceTrigger, 对绑定的数据做自定义转换

[源码下载]

作者:webabcd

介绍
背水一战 Windows 10 之 绑定

  • DataContextChanged - FrameworkElement 的 DataContext 发生变化时触发的事件
  • UpdateSourceTrigger - 数据更新的触发方式
  • 对绑定的数据做自定义转换

示例
1、演示 DataContextChanged 的用法
Bind/DataContextChanged.xaml

<Page
    x:Class="Windows10.Bind.DataContextChanged"
    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">

    <Grid Background="Transparent">

        <StackPanel Margin="10 0 10 10">

            <TextBlock Name="lblMsg" Margin="5" />

            <Button x:Name="btnChange" Content="改变 listBox 的数据上下文" Click="btnChange_Click" Margin="5" />

            <ListBox x:Name="listBox" ItemsSource="{Binding}" DataContextChanged="listBox_DataContextChanged" Background="Orange" Margin="5" />

        </StackPanel>
    </Grid>
</Page>

Bind/DataContextChanged.xaml.cs

/*
 * DataContextChanged - FrameworkElement 的 DataContext 发生变化时触发的事件
 */

using System;
using System.Collections.Generic;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace Windows10.Bind
{
    public sealed partial class DataContextChanged : Page
    {
        public DataContextChanged()
        {
            this.InitializeComponent();

            this.Loaded += DataContextChanged_Loaded;
        }

        private void DataContextChanged_Loaded(object sender, RoutedEventArgs e)
        {
            // 指定数据上下文
            listBox.DataContext = new List<string> { "a", "b", "c" };
        }

        private void btnChange_Click(object sender, RoutedEventArgs e)
        {
            // 修改数据上下文
            listBox.DataContext = new List<string> { "a", "b", new Random().Next(0, 1000).ToString().PadLeft(3, ‘0‘) };
        }

        private void listBox_DataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
        {
            /*
             * FrameworkElement.DataContextChanged - 数据上下文发生改变后触发的事件
             */

            // 数据上下文发生改变后
            lblMsg.Text = "数据上下文发生改变:" + DateTime.Now.ToString("hh:mm:ss");

        }
    }
}

2、演示 UpdateSourceTrigger 的用法
Bind/UpdateSourceTrigger.xaml

<Page
    x:Class="Windows10.Bind.UpdateSourceTrigger"
    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">

    <Grid Background="Transparent">

        <StackPanel Margin="10 0 10 10">

            <TextBlock Name="lblMsg" Foreground="Orange" Margin="5" />

            <!--
                UpdateSourceTrigger - 数据更新的触发方式
                    Default - 失去焦点后触发
                    PropertyChanged - 属性值发生改变后触发
                    Explicit - 需要通过 BindingExpression.UpdateSource() 显示触发
            -->

            <TextBox Text="{Binding Text, Mode=TwoWay, ElementName=lblMsg, UpdateSourceTrigger=Default}" Margin="5" />
            <TextBox Text="{Binding Text, Mode=TwoWay, ElementName=lblMsg, UpdateSourceTrigger=PropertyChanged}" Margin="5" />
            <TextBox Name="txtExplicit" Text="{Binding Text, Mode=TwoWay, ElementName=lblMsg, UpdateSourceTrigger=Explicit}" Margin="5" />

            <Button Name="btnBinding" Content="显示触发更新" Click="btnBinding_Click" Margin="5" />

        </StackPanel>
    </Grid>
</Page>

Bind/UpdateSourceTrigger.xaml.cs

/*
 * UpdateSourceTrigger - 数据更新的触发方式
 *     Default - 失去焦点后触发
 *     PropertyChanged - 属性值发生改变后触发
 *     Explicit - 需要通过 BindingExpression.UpdateSource() 显示触发
 */

using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;

namespace Windows10.Bind
{
    public sealed partial class UpdateSourceTrigger : Page
    {
        public UpdateSourceTrigger()
        {
            this.InitializeComponent();
        }

        private void btnBinding_Click(object sender, RoutedEventArgs e)
        {
            // 显示触发 txtExplicit 的数据更新
            BindingExpression be = txtExplicit.GetBindingExpression(TextBox.TextProperty);
            be.UpdateSource();
        }
    }
}

3、演示如何对绑定的数据做自定义转换
Bind/BindingConverter.xaml

<Page
    x:Class="Windows10.Bind.BindingConverter"
    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">

    <Grid Background="Transparent">
        <StackPanel Margin="10 0 10 10">

            <!--
                配置 IValueConverter 资源
            -->
            <StackPanel.Resources>
                <local:IntegerLetterConverter x:Key="IntegerLetterConverter"/>
            </StackPanel.Resources>

            <Slider Name="slider1" Minimum="97" Maximum="122" Value="1" Width="300" Background="White" HorizontalAlignment="Left" Margin="5" />
            <!--
                演示如何使用 Binding 的 Converter, ConverterParameter, ConverterLanguage
                注:ConverterParameter 和 ConverterLanguage 不支持绑定,只能配置为一个静态的值(但是在 C# 端可以实现一些在 xaml 中无法实现的特性,详见后面的例子)
            -->
            <TextBox Name="textBox1" Width="300" HorizontalAlignment="Left" Margin="5"
                     Text="{Binding ElementName=slider1, Path=Value, Mode=TwoWay,
                                    Converter={StaticResource IntegerLetterConverter},
                                    ConverterParameter=param,
                                    ConverterLanguage=zh}" />

            <Slider Name="slider2" Minimum="97" Maximum="122" Value="1" Width="300" Background="White" HorizontalAlignment="Left" Margin="5" />
            <!--
                在 C# 端使用 Binding 的 Converter, ConverterParameter, ConverterLanguage
            -->
            <TextBox Name="textBox2" Width="300" HorizontalAlignment="Left" Margin="5" />

            <TextBlock Name="lblMsg" TextWrapping="Wrap" />

        </StackPanel>
    </Grid>
</Page>

Bind/BindingConverter.xaml.cs

/*
 * 演示如何对绑定的数据做自定义转换
 */

using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;

namespace Windows10.Bind
{
    public sealed partial class BindingConverter : Page
    {
        public BindingConverter()
        {
            this.InitializeComponent();

            this.Loaded += BindingConverter_Loaded;
        }

        private void BindingConverter_Loaded(object sender, RoutedEventArgs e)
        {
            // 实例化 Binding 对象
            Binding binding = new Binding()
            {
                ElementName = nameof(slider2),
                Path = new PropertyPath(nameof(Slider.Value)),
                Mode = BindingMode.TwoWay, // 默认是 OneWay 的
                Converter = new IntegerLetterConverter(),
                ConverterParameter = lblMsg, // 将 ConverterParameter 设置为一个指定的控件,这个在 xaml 中实现不了,但是可以在 C# 端实现
                ConverterLanguage = "zh"
            };

            // 将目标对象的目标属性与指定的 Binding 对象关联
            BindingOperations.SetBinding(textBox2, TextBox.TextProperty, binding);
        }
    }

    // 自定义一个实现了 IValueConverter 接口的类,用于对绑定的数据做自定义转换
    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 (parameter != null && parameter.GetType() == typeof(TextBlock))
            {
                ((TextBlock)parameter).Text = $"value: {value}, targetType: {targetType}, parameter: {parameter}, language: {language}";
            }

            int v = (int)(double)value;
            return (char)v;
        }

        /// <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 (parameter != null && parameter.GetType() == typeof(TextBlock))
            {
                ((TextBlock)parameter).Text = $"value: {value}, targetType: {targetType}, parameter: {parameter}, language: {language}";
            }

            int v = ((string)value).ToCharArray()[0];
            return v;
        }
    }
}

OK
[源码下载]

时间: 2024-10-29 21:53:01

背水一战 Windows 10 (20) - 绑定: DataContextChanged, UpdateSourceTrigger, 对绑定的数据做自定义转换的相关文章

背水一战 Windows 10 (19) - 绑定: TemplateBinding 绑定, 与 RelativeSource 绑定, 与 StaticResource 绑定

[源码下载] 作者:webabcd 介绍背水一战 Windows 10 之 绑定 TemplateBinding 绑定 与 RelativeSource 绑定 与 StaticResource 绑定 示例1.演示 TemplateBinding 的用法Bind/TemplateBindingDemo.xaml <Page x:Class="Windows10.Bind.TemplateBindingDemo" xmlns="http://schemas.microsof

背水一战 Windows 10 (18) - 绑定: 与 Element 绑定, 与 Indexer 绑定, TargetNullValue, FallbackValue

[源码下载] 作者:webabcd 介绍背水一战 Windows 10 之 绑定 与 Element 绑定 与 Indexer 绑定 TargetNullValue - 当绑定数据为 null 时显示的值 FallbackValue - 当绑定失败时显示的值 示例1.演示如何与 Element 绑定Bind/BindingElement.xaml <Page x:Class="Windows10.Bind.BindingElement" xmlns="http://sc

背水一战 Windows 10 (22) - 绑定: 通过 Binding 绑定对象, 通过 x:Bind 绑定对象, 通过 Binding 绑定集合, 通过 x:Bind 绑定集合

[源码下载] 作者:webabcd 介绍背水一战 Windows 10 之 绑定 通过 Binding 绑定对象 通过 x:Bind 绑定对象 通过 Binding 绑定集合 通过 x:Bind 绑定集合 示例1.演示如何通过 Binding 绑定对象Bind/BindingModel.xaml <Page x:Class="Windows10.Bind.BindingModel" xmlns="http://schemas.microsoft.com/winfx/20

背水一战 Windows 10 (24) - MVVM: 通过 Binding 或 x:Bind 结合 Command 实现,通过非 ButtonBase 触发命令

原文:背水一战 Windows 10 (24) - MVVM: 通过 Binding 或 x:Bind 结合 Command 实现,通过非 ButtonBase 触发命令 [源码下载] 作者:webabcd 介绍背水一战 Windows 10 之 MVVM(Model-View-ViewModel) 通过 Binding 或 x:Bind 结合 Command 实现,通过非 ButtonBase 触发命令 示例1.ModelMVVM/Model/Product.cs /* * Model 层的实

背水一战 Windows 10 (35) - 控件(弹出类): FlyoutBase, Flyout, MenuFlyout

原文:背水一战 Windows 10 (35) - 控件(弹出类): FlyoutBase, Flyout, MenuFlyout [源码下载] 作者:webabcd 介绍背水一战 Windows 10 之 控件(弹出类) FlyoutBase Flyout MenuFlyout 示例1.FlyoutBase(基类) 的示例Controls/FlyoutControl/FlyoutBaseDemo.xaml <Page x:Class="Windows10.Controls.FlyoutC

背水一战 Windows 10 (32) - 控件(选择类): Selector, ComboBox

原文:背水一战 Windows 10 (32) - 控件(选择类): Selector, ComboBox [源码下载] 作者:webabcd 介绍背水一战 Windows 10 之 控件(选择类) Selector ComboBox 示例1.Selector(基类) 的示例Controls/SelectionControl/SelectorDemo.xaml <Page x:Class="Windows10.Controls.SelectionControl.SelectorDemo&q

背水一战 Windows 10 (31) - 控件(按钮类): ButtonBase, Button, HyperlinkButton, RepeatButton, ToggleButton, AppBarButton, AppBarToggleButton

原文:背水一战 Windows 10 (31) - 控件(按钮类): ButtonBase, Button, HyperlinkButton, RepeatButton, ToggleButton, AppBarButton, AppBarToggleButton [源码下载] 作者:webabcd 介绍背水一战 Windows 10 之 控件(按钮类) ButtonBase Button HyperlinkButton RepeatButton ToggleButton AppBarButto

背水一战 Windows 10 (26) - XAML: x:DeferLoadStrategy, x:Null

原文:背水一战 Windows 10 (26) - XAML: x:DeferLoadStrategy, x:Null [源码下载] 作者:webabcd 介绍背水一战 Windows 10 之 XAML x:DeferLoadStrategy="Lazy" - 用于指定一个 UIElement 为一个延迟加载元素 x:Null - null 示例1.x:DeferLoadStrategy 通过 FindName 加载Xaml/DeferLoadStrategy/Demo1.xaml

背水一战 Windows 10 (23) - MVVM: 通过 Binding 或 x:Bind 结合 Command 实现,通过 ButtonBase 触发命令

[源码下载] 作者:webabcd 介绍背水一战 Windows 10 之 MVVM(Model-View-ViewModel) 通过 Binding 或 x:Bind 结合 Command 实现,通过 ButtonBase 触发命令 示例1.ModelMVVM/Model/Product.cs /* * Model 层的实体类,如果需要通知则需要实现 INotifyPropertyChanged 接口 */ using System.ComponentModel; namespace Wind