WPF数据绑定

WPF数据绑定简介

句法

{Binding PropertyName} 相当于 {Binding Path = PropertyName}

{Binding Path = SomeProperty.SomeOtherProperty.YetAnotherProperty}

{Binding Path = SomeListProperty [1]}

参数

参数

细节

Path路径

指定要绑定的路径。如果未指定,则绑定到DataContext本身。

UpdateSourceTrigger

指定绑定源何时更新其值。默认为LostFocus 。最常用的值是PropertyChanged 

Mode模式

通常是OneWayTwoWay 。如果绑定未指定,则默认为OneWay除非绑定目标请求它为TwoWay 。当TwoWay用于绑定到readonly属性时发生错误,例如,在将readonly字符串属性绑定到TextBox.Text时必须显式设置OneWay 

Source资源

允许使用StaticResource作为绑定源而不是当前的DataContext

RelativeSource

允许使用另一个XAML元素作为绑定源而不是当前的DataContext

ElementName

允许使用命名的XAML元素作为绑定源而不是当前的DataContext

FallbackValue

如果绑定失败,则将此值提供给绑定目标。

TargetNullValue

如果绑定源值为null ,则将此值提供给绑定目标。

Converter

指定用于转换绑定值的转换器StaticResource ,例如将布尔值转换为Visibility枚举项。

ConverterParameter

指定要提供给转换器的可选参数。该值必须是静态的,不能绑定。

StringFormat

指定显示绑定值时要使用的格式字符串。

Delay延迟

WPF 4.5+)指定绑定更新ViewModel BindingSource的延迟(以millisecondsmilliseconds )。这必须与Mode=TwoWayUpdateSourceTrigger=PropertyChanged一起使用才能生效。

备注

UpdateSourceTrigger:

默认情况下,WPF在控件失去焦点时更新绑定源。但是,如果只有一个控件可以获得焦点 - 这在示例中很常见 - 需要指定UpdateSourceTrigger=PropertyChanged才能使更新UpdateSourceTrigger=PropertyChanged 

将希望使用PropertyChanged作为许多双向绑定的触发器,除非在每次击键时更新绑定源代价高昂或者不希望进行实时数据验证。

使用LostFocus有一个不幸的副作用:按Enter键以使用标记为IsDefault的按钮提交表单不会更新支持绑定的属性,从而有效地撤消的更改。幸运的是, 存在一些变通方法 

还请注意,与UWP不同,WPF4.5+)在绑定中也具有Delay属性,对于某些具有本地或简单的次要智能设置的绑定可能就足够了,例如一些TextBox验证。

wpf使用MultiBinding绑定多个值

MultiBinding允许将多个值绑定到同一属性。在以下示例中,多个值绑定到TextboxText属性,并使用StringFormat属性进行格式化。

<TextBlock>

    <TextBlock.Text>

        <MultiBinding StringFormat="{}{0} {1}">

            <Binding Path="User.Forename"/>

            <Binding Path="User.Surname"/>

        </MultiBinding>

    </TextBlock.Text>

</TextBlock>

除了StringFormat之外,还可以使用IMultiValueConverterBindings中的值转换为MultiBinding目标的一个值。

但是,MultiBindings不能嵌套。

wpf定义DataContext

要在WPF中使用绑定,需要定义DataContext DataContext告诉绑定默认情况下从哪里获取数据。

<Window x:Class="StackOverflowDataBindingExample.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:StackOverflowDataBindingExample"

        xmlns:vm="clr-namespace:StackOverflowDataBindingExample.ViewModels"

        mc:Ignorable="d"

        Title="MainWindow" Height="350" Width="525">

    <Window.DataContext>

        <vm:HelloWorldViewModel />

    </Window.DataContext>

    ...

</Window>

也可以通过代码隐藏设置DataContext,但值得注意的是XAML IntelliSense有点挑剔:必须在XAML中为IntelliSense设置强类型DataContext,以建议可用于绑定的属性。

/// <summary>

///MainWindow.xaml的交互逻辑

/// </summary>

public partial class MainWindow : Window

{

    public MainWindow()

    {

        InitializeComponent();

        DataContext = new HelloWorldViewModel();

    }

}

有一些框架可以帮助以更灵活的方式定义DataContext(例如MVVM Light有一个使用控制反转的 viewmodel定位器)。

 

可以为WPF中的几乎任何可视元素定义DataContextDataContext通常从可视树中的祖先继承,除非它已被显式覆盖,例如在ContentPresenter中。

实现INotifyPropertyChanged

INotifyPropertyChanged是绑定源(即DataContext)使用的接口,以使用户界面或其他组件知道属性已更改。当WPF看到引发的PropertyChanged事件时,它会自动为更新UI。希望在所有视图模型都可以继承的基类上实现此接口。

C#6

public abstract class ViewModelBase : INotifyPropertyChanged

{

    public event PropertyChangedEventHandler PropertyChanged;

 

    protected void NotifyPropertyChanged([CallerMemberName] string name = null)

    {

        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));

    }

}

这允许以两种不同的方式调用NotifyPropertyChanged 

  1. NotifyPropertyChanged() ,它将引发调用它的setter的事件,这要归功于CallerMemberName属性。
  2. NotifyPropertyChanged(nameof(SomeOtherProperty)) ,它将为SomeOtherProperty引发事件。

对于使用C:5.0.NET 4.5及更高版本:

public abstract class ViewModelBase : INotifyPropertyChanged

{

    public event PropertyChangedEventHandler PropertyChanged;

 

    protected void NotifyPropertyChanged([CallerMemberName] string name = null)

    {

        var handler = PropertyChanged;

        if (handler != null)

        {

            handler(this, new PropertyChangedEventArgs(name));

        }

    }

}

4.5之前的.NET版本中,必须将属性名称解析为字符串常量或使用表达式的解决方案 

 

注意:可以绑定到未实现INotifyPropertyChanged“plain old C# objectPOCO)的属性,并观察绑定是否比预期更好。这是.NET中的一个隐藏功能,应该可以避免。特别是当绑定的Mode不是OneTime时会导致内存泄漏(见这里 )。

为什么绑定更新没有实现INotifyPropertyChanged

将布尔值转换为可见性值

如果未使用IValueConverter检查复选框,则此示例隐藏红色框(边框)。

注意:以下BooleanToVisibilityConverter使用的BooleanToVisibilityConverter是一个内置值转换器,位于System.Windows.Controls命名空间中。

XAML

<Window x:Class="StackOverflowDataBindingExample.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="MainWindow" Height="350" Width="525">

    <Window.Resources>

        <BooleanToVisibilityConverter x:Key="VisibleIfTrueConverter" />

    </Window.Resources>

    <StackPanel>

        <CheckBox x:Name="MyCheckBox"

                  IsChecked="True" />

        <Border Background="Red" Width="20" Height="20"

                Visibility="{Binding Path=IsChecked,ElementName=MyCheckBox, Converter={StaticResource VisibleIfTrueConverter}}" />

    </StackPanel>

</Window>

绑定到另一个命名元素的属性

可以绑定到命名元素上的属性,但命名元素必须在范围内。

<StackPanel>

    <CheckBox x:Name="MyCheckBox" IsChecked="True" />

    <TextBlock Text="{Binding IsChecked, ElementName=MyCheckBox}" />

</StackPanel>

绑定祖先的财产

可以使用RelativeSource绑定绑定到可视树中的祖先的属性。可视树中具有相同类型或从指定的类型派生的最近控件将用作绑定的源:

<Grid Background="Blue">

    <Grid Background="Gray" Margin="10">

        <Border Background="Red" Margin="20">

            <StackPanel Background="White" Margin="20">

                <Button Margin="10" Content="Button1" Background="{Binding Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Grid}}}" />

                <Button Margin="10" Content="Button2" Background="{Binding Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type FrameworkElement}}}" />

            </StackPanel>

        </Border>

    </Grid>

</Grid>

在此示例中, Button1具有灰色背景,因为最近的Grid祖先具有灰色背景。 Button2具有白色背景,因为从FrameworkElement派生的最近的祖先是白色StackPanel 

posted @ 2020-01-03 10:56  N-COUNT  阅读(709)  评论(0编辑  收藏  举报