WPF-数据绑定Binding

565 阅读3分钟

一、 绑定表达式

数据绑定是将两个数据/信息源绑定在一起并保持数据同步的通用技术。

<TextBox x:Name="sourceTBox" Text="hello world!" /> 
<TextBlock x:Name="tb" Text="{Binding ElementName=sourceTBox,Path=Text,Mode=Default}" />

1651030588(1).jpg

绑定关系由四个方面组成:

1.绑定目标 指包含绑定表达式的控件元素 如:TextBlock

2.绑定目标属性 控件的属性设置了绑定表达式,这个属性就是目标属性 如:TextBlock的Text属性

3.绑定源 绑定表达式中 ElementName 属性所指向的元素

4.绑定源属性 绑定源的属性

二、绑定模式

当设置 Binding.Mode 属性时。WPF 允许使用 5 个 system.windows.data.BindingMode 枚举值中的任何一个。代码如下,其中的 Mode=TwoWay 就是设置绑定模式

枚举名称说明
OneWay当源属性变化时更新目标属性
TwoWay当源属性变化时更新目标属性 ,当目标属性 变化时更新源属性
OneTime最初设定源属性时更新目标属性,后期的变化都被忽略 ,如果知道源属性不会变化,可以使用这种模式,降低开销
OneWayToSource与OneWay 类似,但方向相反,当目标属性变化时更新源属性,有点向后传递,但目标属性永远不会被更新
Default此类绑定依赖于目标属性,即可以是双向(对于用户可以设置的属性,如TextBlock.Text,) 也可以是单向,除非明确指明一种模式,否则都采用此种模式

下图可以帮助我们更好的理解数据绑定:

2037316-20210913155347786-2952933270000.jpg

三、绑定更新

 <TextBlock x:Name="tb" Text="{Binding Text,ElementName=sourceTBox,Mode=TwoWay,UpdateSourceTrigger=Default}" />

关键属性:UpdateSourceTrigger,枚举值:

名称说明
PropertyChanged属性发生变化时更新
LostFous失去焦点时更新
Explicit调用 BindingExpress.UpdateSource()时更新
Defeat根据属性的元数据确定更新行为(FrameworkPropertyMetadata.DefaultUpdateSourceTriggere) 大多数默认行为 是PropertyChanged 但TextBox.Text 默认行为是 LostFocus

四、延迟绑定

<TextBlock x:Name="tb" Text="{Binding Text,ElementName=sourceTBox,Mode=TwoWay,Delay=500}" />

关键属性:Delay

作用 :避免过分频繁的触发操作,导致频繁更新UI。

使用 Binding 对像的 Delay 属性。等待数毫秒之后再提交更新。

五、RelativeSource 相对绑定

<TextBlock  Text="{Binding Title,RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType={x:Type Window}}}" />

可以使用RelativeSource 属性将元素绑定 自身 或 父元素

  • 绑定到父元素 Mode=FindAncestor

  • 绑定到自身 Mode="Self"

  • 绑定到列表数据中的前一个数据项 Mode="PreviousData"

  • 绑定到应用模板元素 Mode="TemplatedParent"

六、DataContent属性

<TextBlock Text="{Binding Version}" />
//Window 对像DataContent 属性引用对像  SystemVersion
public class SystemVersion{
    public int Code { get; set; }
    public String Version { get; set; }
}

//设置 Window 对像DataContent 属性
this.DataContext = new SystemVersion()
{
    Code = 103,
    Version = "V1.0.3"
};

Wpf就从当前元素开始在元素树中向上查找。检查每一个元素的DataContent属性,并使用 第一个非空的DataContent 属性 所引用的对像的 Version 属性。

如果 TextBlock的Text 直到 Window 对像DataContent 属性引用一个对像不为空,TextBlock的Text 就绑定到 Window 对像DataContent 属性引用对像的 Version 属性上。

七、绑定转换

对于简单的数据格式化,可以通过StringFormat来处理

   <StackPanel x:Name="simpleconvert">
        <TextBlock Text="{Binding Date,StringFormat=yyyy-MM-dd}" />
        <TextBlock Text="{Binding Price,StringFormat=f2}" />
    </StackPanel>
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.simpleconvert.DataContext = new SimpleDataConvert();
        }
    }

    class SimpleDataConvert
    {
        public DateTime Date { get; set; } = DateTime.Now;
        public float Price { get; set; } = 100.123456f;
    }

image.png

无法通过StingFormat处理的数据,则需要使用Converter属性来处理,即转换器,

<Window x:Class="WpfDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfDemo"
        xmlns:utils="clr-namespace:WpfDemo.Utils"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <utils:DataConverter x:Key="dataconvert" />
    </Window.Resources>
    
    <StackPanel Margin="100,200,100,100">
        <StackPanel x:Name="simpleconvert">
            <TextBox Text="{Binding Price,Converter={StaticResource dataconvert}}" />
        </StackPanel>
    </StackPanel>
</Window>

namespace WpfDemo
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.simpleconvert.DataContext = new SimpleDataConvert();
        }
    }

    class SimpleDataConvert
    {
        public DateTime Date { get; set; } = DateTime.Now;
        public float Price { get; set; } = 100.12f;
    }
}
namespace WpfDemo.Utils
{
    public class DataConverter : IValueConverter
    {
        /// <summary>
        /// 数据源转界面显示
        /// </summary>
        /// <param name="value"></param>
        /// <param name="targetType"></param>
        /// <param name="parameter"></param>
        /// <param name="culture"></param>
        /// <returns></returns>
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value != null)
            {
                return "$" + value;
            }
            else
            {
                return value;
            }
        }

        /// <summary>
        /// 界面显示转数据源
        /// </summary>
        /// <param name="value"></param>
        /// <param name="targetType"></param>
        /// <param name="parameter"></param>
        /// <param name="culture"></param>
        /// <returns></returns>
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value != null && value.ToString().StartsWith("$"))
            {
                return value.ToString().Trim('$');
            }
            else
            {
                return value;
            }
        }
    }
}

image.png