WPF QuickStart系列之数据绑定(Data Binding)

这篇博客将展示WPF DataBinding的内容。

首先看一下WPF Data Binding的概览,

Binding Source可以是任意的CLR对象,或者XML文件等,Binding Target需要有依赖属性。这样便可以进行Data Binding。请看下面的示例,

C#

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            DataContext = new Person() { Name = "Tom", Age = 25 };
        }
    }

    public class Person
    {
        public string Name { get; set; }

        public int Age { get; set; }
    }

XAML:

    <Grid>
        <StackPanel>
            <TextBlock Text="{Binding Name}" Margin="10,5"/>
            <TextBlock Text="{Binding Age}" Margin="10,5"/>
        </StackPanel>
    </Grid>

运行结果: 

下面通过一些例子来介绍在Data Binding,

1. 我们可以在XAML中,指定Binding Target的ElementName和Path属性来获取Binding Source的数据,例如,

XAML:

        <StackPanel>
            <Slider x:Name="_slider" Minimum="0" Maximum="100" Value="20"/>
            <TextBox Text="{Binding ElementName=_slider,Path=Value}"/>
        </StackPanel>

运行结果: 

上面XAML代码中,将Slider的Value属性Binding到TextBox。

通过上面的Gif图片可以发现,当拖动Slider时,TextBox框中的数值随着Slider的Value改变而改变,当在TextBox中输入数值时,按Tab键失去焦点后,Slider的Value发生了改变。这是因为TextBox的默认Binding Mode为TwoWay,且UpdateSoureTrigger默认为LostFocus。请看下面的BindingMode示意图,

图示中有种Binding Mode,

OneWay,数据流向是从Source到Target;

TwoWay,数据可以从Source到Target,也可以从Target到Source,

OneWayToSource与OneWay相反,

OneTime,表示数据绑定发生后,数据源无论如何改变,Target中绑定的值都不会发生改变。

下面我们通过例子来演示这4种绑定

XAML:

<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <!--OneWay Binding-->
        <StackPanel>
            <TextBlock Text="Binding Mode: OneWay"/>
            <Slider x:Name="_slider" Minimum="0" Maximum="100" Value="20"/>
            <TextBox Text="{Binding ElementName=_slider,Path=Value,Mode=OneWay}"/>
        </StackPanel>

        <!--OneTime Binding-->
        <StackPanel Grid.Row="1" Margin="0,20">
            <TextBlock Text="Binding Mode: OneTime"/>
            <Slider x:Name="_slider1" Minimum="0" Maximum="100" Value="20"/>
            <TextBox Text="{Binding ElementName=_slider1,Path=Value,Mode=OneTime}"/>
        </StackPanel>

        <!--OneWayToSource Binding-->
        <!--将TextBox的FontSize默认值为12-->
        <StackPanel Grid.Row="2">
            <TextBlock Text="Binding Mode: OneWayToSource"/>
            <Slider x:Name="_slider2" Minimum="0" Maximum="100" Value="20"/>
            <TextBox FontSize="{Binding ElementName=_slider2,Path=Value, Mode=OneWayToSource}"
                     Text="{Binding RelativeSource={RelativeSource Self},Path=FontSize}"/>
        </StackPanel>

        <!--TwoWay Binding-->
        <StackPanel Grid.Row="3" Margin="0,20">
            <TextBlock Text="Binding Mode: TwoWay"/>
            <Slider x:Name="_slider3" Minimum="0" Maximum="100" Value="20"/>
            <TextBox Text="{Binding ElementName=_slider3,Path=Value,Mode=TwoWay}"/>
        </StackPanel>
    </Grid>

运行结果: 

在项目开发中根据实际需要选择不同的Binding Mode,如果某些数据只在程序启动时显示,后面对数据进行修改了,不需要更新,可以选择OneTime Mode;如果对数据进行实时展示,可以选择OneWay Mode;如果需要将数据的修改同步,那么我们选择TwoWay Mode。合适的绑定模式可以最优化程序的性能。

接下来看UpdateSourceTrigger,UpdateSourceTrigger有下面几种取值,

1. LostFocus, 例如TextBox失去焦点后更新Source;

2. PropertyChanged,例如当在TextBox中输入时,Source便同步更新;

3. Explict,需要显示的调用UpdateSource方法;

下面我们看Binding中另一个概念Converter;看这样一个例子,有一个文本框显示当前温度,如果温度大于35,则将文本框的前景色设置为红色,如果温度小于0,则显示为蓝色;

XAML:

    <Window.Resources>
        <local:TemperatureToBrushCoverter Hot="35" Cold="0" x:Key="TemperatureToBrushCoverter"/>
    </Window.Resources>
    <Grid>
        <TextBox Text="30" Width="200" Height="25"
                     Foreground="{Binding Path=Text,RelativeSource={RelativeSource Self},
                     Converter={StaticResource TemperatureToBrushCoverter}}"/>
    </Grid>

C#:

    [ValueConversion(typeof(double),typeof(Brush))]
    public class TemperatureToBrushCoverter : IValueConverter
    {
        public double Hot { get; set; }

        public double Cold { get; set; }

        public TemperatureToBrushCoverter()
        {

        }

        public TemperatureToBrushCoverter(double hot,double cold)
            :this()
        {
            Hot = hot;
            Cold = cold;
        }

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            double temp;

            Brush brush = Brushes.Black;

            if(Double.TryParse((string)value,out temp))
            {
                if(temp > Hot)
                {
                    brush = Brushes.Red;
                }
                else if(temp < Cold)
                {
                    brush = Brushes.Blue;
                }
            }

            return brush;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

运行结果:

注意要在XAML中引用Converter。

最后我们看一下DataBinding中的数据验证;来看这样一个例子,将Person对象的Age绑定到一个TextBox上,并可以对Age进行修改,年龄是一个有实际意义的值,如果Age小于0或者大于120,我们均认为其为非法值,给出相应提示。请看下面的代码:

XAML:

    <Grid>
        <TextBox Width="200" Height="25">
            <TextBox.Text>
                <Binding Path="Age" UpdateSourceTrigger="PropertyChanged">
                    <Binding.ValidationRules>
                        <local:AgeValidationRule ValidationStep="RawProposedValue"/>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
            <!--Error Template-->
            <Validation.ErrorTemplate>
                <ControlTemplate>
                    <StackPanel>
                        <AdornedElementPlaceholder/>
                        <TextBlock Text="{Binding [0].ErrorContent}" Foreground="Red"/>
                    </StackPanel>
                </ControlTemplate>
            </Validation.ErrorTemplate>
        </TextBox>
    </Grid>

C#:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            DataContext = new Person() { Age = 25};
        }
    }

    public class Person
    {
        public int Age { get; set; }

    }

    public class AgeValidationRule : ValidationRule
    {
        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            int age;

            if(int.TryParse((string)value,out age))
            {
                if(age< 0 || age > 120)
                {
                    return new ValidationResult(false, "This is invalide age.");
                }
                else
                {
                    return new ValidationResult(true, null);
                }
            }

            return new ValidationResult(false, "Please input valid age.");
        }
    }

运行结果:

这篇博客的内容就到这里了,但是WPF中Data Binding的内容远不止这些,会在后面的博客中展现。

感谢您的阅读!代码点击这里下载。

时间: 2024-10-13 20:48:54

WPF QuickStart系列之数据绑定(Data Binding)的相关文章

WPF QuickStart系列

接触WPF有一段时间了,现在做的项目也是WPF相关的.所以决定写一个WPF QuickStart系列的文章.也是自己对WPF学习的总结,如果对你有帮助,我也非常开心.因为不善言辞,所以尽量以WPF示例和代码注释的形式来写这一个系列的博客.当中也会有一些自己对WPF特性的理解写下来,锻炼自己的文笔和语言组织能力.下面是写博客的计划, 1.附加属性(Attached Property): 2.依赖属性(Dependency Property): 3.数据绑定(Data Binding): 4.模板和

WPF中的数据绑定Data Binding使用小结

完整的数据绑定的语法说明可以在这里查看: http://www.nbdtech.com/Free/WpfBinding.pdf MSDN资料: Data Binding: Part 1 http://msdn.microsoft.com/en-us/library/aa480224.aspx Data Binding: Part 2 http://msdn.microsoft.com/en-us/library/aa480226.aspx Data Binding Overview http:/

WPF学习09:数据绑定之 Binding to List Data

从WPF学习03:Element Binding我们可以实现控件属性与控件属性的绑定. 从WPF学习07:MVVM 预备知识之数据绑定 我们可以实现控件属性与自定义对象属性的绑定. 而以上两个功能在实际应用中还是不够的,我们经常需要将列表数据与控件属性进行绑定. 例子 ListBox切换人物,下面两个文本框跟随切换,很常用的功能. XAML代码: <Window x:Class="DataTemplate.MainWindow" xmlns="http://schema

WPF QuickStart系列之样式和模板(Style and Template)

在WPF桌面程序中,当我们想构建一个统一的UI表现时(在不同操作系统下,显示效果一致),此时我们就需要使用到WPF中的样式和模板技术.简单来说,如果我们需要简单的给一个Button设置宽,高,Margin等,可以使用Style来指定这一系列的属性.可以把Style理解为一个属性的集合.如果需要完全改变控件的样子,就需要使用到Template技术,相当于给控件换一层皮,不过Button还是Button,它原有的行为(Click事件)还存在.而且我们仅需要在XAML中遍可以完成对样式和模板的定义和重

WPF QuickStart系列之样式和模板(Style and Template) Part1

在WPF桌面程序中,当我们想构建一个统一的UI表现时(在不同操作系统下,显示效果一致),此时我们就需要使用到WPF中的样式和模板技术.简单来说,如果我们需要简单的给一个Button设置宽,高,Margin等,可以使用Style来指定这一系列的属性.可以把Style理解为一个属性的集合.如果需要完全改变控件的样子,就需要使用到Template技术,相当于给控件换一层皮,不过Button还是Button,它原有的行为(Click事件)还存在.而且我们仅需要在XAML中遍可以完成对样式和模板的定义和重

WPF QuickStart系列之附加属性(Attached Property)

这一篇博客是关于如何使用附加属性和创建自定义附加属性的. 1. 附加属性使用, WPF中对附加属性使用最多的莫过于对控件布局时设置控件的位置,例如在Canvas中有一个Rectangle, Ellipse, Button,我们需要设置它们的位置, <Canvas> <Rectangle x:Name="_rect" Fill="LightBlue" Width="100" Height="50" Canvas

WP8.1 Study5:Data binding数据绑定

一.数据绑定 最简单的编程UI控件的方法是写自己的数据来获取和设置控件的属性,e.g. , textBox1.Text = "Hello, world"; 但在复杂的应用程序,这样的代码很快就会变得笨拙,容易出错 因此,为了更加方便,使用XAML数据绑定到你的UI链接到一个在应用程序中包含应用程序的数据的类. 这个类class:是一个对于被称为视图模型的数据绑定(ViewModel)的数据源. UI控件可以从视图模型Viewmodel类的属性自动获取其显示值,而且通过改变Viewmod

Data Binding和INotifyPropertyChanged是如何协调工作的?

前言 WPF的一大基础就是Data Binding.在基于MVVM架构的基础上,只有通过实现INotifyPropertyChanged接口的ViewModel才能够用于Data Binding. 要实现INotifyPropertyChanged接口,只需要实现一个事件,event PropertyChangedEventHandler PropertyChange. delegate & event基础知识回顾 先来回顾下C#里delegate和event的基础知识. 我们知道在C#里,ev

MvvmLight学习篇—— Mvvm Light Toolkit for wpf/silverlight系列(导航)

一.Mvvm Light Toolkit for wpf/silverlight系列之准备工作 二.Mvvm Light Toolkit for wpf/silverlight系列之搭建mvvmlight开发框架 三.Mvvm Light Toolkit for wpf/silverlight系列之数据绑定 四.Mvvm Light Toolkit for wpf/silverlight系列之Command和Events 五.Mvvm Light Toolkit for wpf/silverli