zoukankan      html  css  js  c++  java
  • WPF---数据绑定(一)

    一、何为数据绑定

    场景:考虑一个Window上有一个TextBox和一个Slider两个元素,当我拖动滑动条的时候,会在TextBox中显示当前滑动条的数值;当我们在TextBox中输入一个有效值,滑动条

    中的滑块会滑到TextBox中输入的值所对应的位置。

    定义:数据绑定可以理解为两个对象之间的一种关联,对象中的某个属性总是保持同步于另个对象的某个属性值。我们可以形象的把绑定比作一个桥梁,它负责同步桥头两侧的物体。

    保持同步的数据元素必须是属性,一个叫源属性,一个叫目标属性;

    目标属性必须是一个依赖属性。

    二、如何绑定元素对象

    关于上面滑动条和文本框的绑定,我们可以用以下Xaml代码实现:

    <Window x:Class="BindingDemo1.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:BindingDemo1"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <StackPanel>
                <TextBox Name="tbx" Text="{Binding Path=Value, ElementName=sldrSlider}" ></TextBox>
                <Slider Name="sldrSlider" Minimum="0" Maximum="100"></Slider>
            </StackPanel>
        </Grid>
    </Window>

    等价的后台代码实现如下:

    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    
    namespace BindingDemo1
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
               // Binding binding = new Binding() { ElementName = "sldrSlider",Path= new PropertyPath("Value")};
                Binding binding = new Binding("Value") { ElementName = "sldrSlider" };
                tbx.SetBinding(TextBox.TextProperty, binding);
            }
        }
    }

    后台代码主要完成了以下功能:
     1)创建一个binding对象;

     2)设置了binding对象的Source和Path值;

     3)调用了目标(textbox)的SetBinding方法创建一个binding表达式,它连接了binding对象和目标依赖属性。

    三、数据绑定的方向

    我们可以通过设置Binding对象Mode属性控制数据绑定的方向

    OneWay:数据源改变时,更新目标;

    TwoWay:双向更新;

    OneWayToSource:目标改变时,更新数据源;

    OneTime:只更新目标一次,使用数据源的初值,以后目标不再被更新;

    Default:使用目标的默认绑定模式。

    四、触发器---更新数据源的时机

    仍然考虑上面滑动条和文本框的绑定关系,我们会发现当文本框的数值改变后,滑动条的滑块不会立即改变,而是在文本框失去焦点的时候,才会改变。

    这就涉及到当目标属性变化的时候,数据源如何以及何时变化。

    关于数据的更新方向和时机,可以参见下图:

    当目标依赖属性发生变化,我们可以利用Binding对象的UpdateSourceTrigger属性来控制何时更新数据源,UpdateSourceTrigger属性值包括以下:

    注:UpdateSourceTrigger属性值不影响目标的更新方式,它仅仅控制TwoWay模式或OneWayToSource模式的绑定更新源的方式。

    而文本框正是使用LostFocus方式从目标向源进行更新的。

    如果要完全控制源对象的更新时机,则可以选择UpdateSourceTrigger.Explicit模式

    此时就需要额外编写代码手动触发更新。可以添加一个Apply按钮,并在按钮的Click事件处理程序中调用BindingExpression.UpdateSource方法立即更新数据源。

    参考代码以下:

     1 <Window x:Class="BindingDemo1.MainWindow"
     2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     6         xmlns:local="clr-namespace:BindingDemo1"
     7         mc:Ignorable="d"
     8         Title="MainWindow" Height="350" Width="525">
     9     <Grid>
    10         <StackPanel>
    11             <TextBox Name="tbx" Text="{Binding Path=Value, ElementName=sldrSlider,UpdateSourceTrigger=Explicit}" ></TextBox>
    12             <Slider Name="sldrSlider" Minimum="0" Maximum="100"></Slider>
    13             <Button Height="30" Width="100" Content="Apply" Click="Button_Click"></Button>
    14         </StackPanel>
    15     </Grid>
    16 </Window>
    View Code
     1 using System.Windows;
     2 using System.Windows.Controls;
     3 using System.Windows.Data;
     4 
     5 namespace BindingDemo1
     6 {
     7     /// <summary>
     8     /// Interaction logic for MainWindow.xaml
     9     /// </summary>
    10     public partial class MainWindow : Window
    11     {
    12         public MainWindow()
    13         {
    14             InitializeComponent();
    15            //Binding binding = new Binding() { ElementName = "sldrSlider",Path= new PropertyPath("Value")};
    16            //Binding binding = new Binding("Value") { ElementName = "sldrSlider" ,UpdateSourceTrigger=UpdateSourceTrigger.};
    17            //tbx.SetBinding(TextBox.TextProperty, binding);
    18         }
    19 
    20         private void Button_Click(object sender, RoutedEventArgs e)
    21         {
    22             //获得应用于文本框上的绑定
    23             BindingExpression be = tbx.GetBindingExpression(TextBox.TextProperty);
    24             //调用UpdateSource更新源对象
    25             be.UpdateSource();
    26         }
    27     }
    28 }
    View Code

     五、转换器

    上面的例子中,当拖动滑动条的时候,文本框中显示的数字会显示好多位小数,现在我们想让在文本框中只显示两位小数,这时候就需要转换器来实现了。

    定义:转化器是一个类,用于拦截数据源和目标之间的数据,拦截之后,就可以按照我们的意愿对数据进行操作。

    转换器包括单值转换器多值转换器。单值转换器需要实现IValueConverter接口,多值转换器需要实现IMultiValueConverter接口。

    对于上面的需求,我们可以使用单值转换器,参考代码如下:

     1 using System;
     2 using System.Globalization;
     3 using System.Windows;
     4 using System.Windows.Controls;
     5 using System.Windows.Data;
     6 
     7 namespace BindingDemo1
     8 {
     9     /// <summary>
    10     /// Interaction logic for MainWindow.xaml
    11     /// </summary>
    12     public partial class MainWindow : Window
    13     {
    14         public MainWindow()
    15         {
    16             InitializeComponent();
    17            //Binding binding = new Binding() { ElementName = "sldrSlider",Path= new PropertyPath("Value")};
    18            //Binding binding = new Binding("Value") { ElementName = "sldrSlider" ,UpdateSourceTrigger=UpdateSourceTrigger.};
    19            //tbx.SetBinding(TextBox.TextProperty, binding);
    20         }
    21 
    22         private void Button_Click(object sender, RoutedEventArgs e)
    23         {
    24             //获得应用于文本框上的绑定
    25             BindingExpression be = tbx.GetBindingExpression(TextBox.TextProperty);
    26             //调用UpdateSource更新源对象
    27             be.UpdateSource();
    28         }
    29     }
    30     public class SliderValue2StringConverter:IValueConverter
    31     {
    32         public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    33         {
    34             double valueFromSource = (double)value;
    35             return valueFromSource.ToString("F2");//保留两位小数
    36         }
    37  
    38         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    39         {
    40             throw new NotImplementedException("Method ConvertBack not implemented");
    41         }
    42     }
    43 }
    View Code
     1 <Window x:Class="BindingDemo1.MainWindow"
     2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     6         xmlns:local="clr-namespace:BindingDemo1"
     7         mc:Ignorable="d"
     8         Title="MainWindow" Height="350" Width="525">
     9     <Window.Resources>
    10         <local:SliderValue2StringConverter x:Key="s2vCvt"></local:SliderValue2StringConverter>
    11     </Window.Resources>
    12     <Grid>
    13         <StackPanel>
    14             <TextBox Name="tbx" Text="{Binding Path=Value, ElementName=sldrSlider,UpdateSourceTrigger=Explicit,Converter={StaticResource ResourceKey=s2vCvt}}" ></TextBox>
    15             <Slider Name="sldrSlider" Minimum="0" Maximum="100"></Slider>
    16             <Button Height="30" Width="100" Content="Apply" Click="Button_Click"></Button>
    17         </StackPanel>
    18     </Grid>
    19 </Window>
    View Code

    现在考虑以下场景,我们有一个椭圆,椭圆的颜色是根据RGB三个不同的分量变化的,我们让三个滑动条分别控制RGB三个分量,下面就用多值转换器进行实现。

     1 using System;
     2 using System.Globalization;
     3 using System.Windows;
     4 using System.Windows.Controls;
     5 using System.Windows.Data;
     6 using System.Windows.Media;
     7 
     8 namespace BindingDemo1
     9 {
    10     /// <summary>
    11     /// Interaction logic for MainWindow.xaml
    12     /// </summary>
    13     public partial class MainWindow : Window
    14     {
    15         public MainWindow()
    16         {
    17             InitializeComponent();
    18            //Binding binding = new Binding() { ElementName = "sldrSlider",Path= new PropertyPath("Value")};
    19            //Binding binding = new Binding("Value") { ElementName = "sldrSlider" ,UpdateSourceTrigger=UpdateSourceTrigger.};
    20            //tbx.SetBinding(TextBox.TextProperty, binding);
    21         }
    22 
    23         private void Button_Click(object sender, RoutedEventArgs e)
    24         {
    25             //获得应用于文本框上的绑定
    26             BindingExpression be = tbx.GetBindingExpression(TextBox.TextProperty);
    27             //调用UpdateSource更新源对象
    28             be.UpdateSource();
    29         }
    30     }
    31     public class SliderValue2StringConverter:IValueConverter
    32     {
    33         public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    34         {
    35             double valueFromSource = (double)value;
    36             return valueFromSource.ToString("F2");//保留两位小数
    37         }
    38  
    39         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    40         {
    41             throw new NotImplementedException("Method ConvertBack not implemented");
    42         }
    43     }
    44     public class Rgb2ColorConverter : IMultiValueConverter
    45     {
    46         //正向修改,整合颜色值
    47         public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    48         {
    49             if (values == null || values.Length < 3)
    50                 return null;
    51             byte r = System.Convert.ToByte(values[0]);
    52             byte g = System.Convert.ToByte(values[1]);
    53             byte b = System.Convert.ToByte(values[2]);
    54             Color myColor = Color.FromRgb(r, g, b);
    55             SolidColorBrush myBrush = new SolidColorBrush(myColor);
    56             return myBrush;
    57         }
    58         public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    59         {
    60             throw new NotImplementedException("Method ConvertBack not implemented");
    61         }
    62 
    63     }
    64 }
    View Code
     1 <Window x:Class="BindingDemo1.MainWindow"
     2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     6         xmlns:local="clr-namespace:BindingDemo1"
     7         mc:Ignorable="d"
     8         Title="MainWindow" Height="350" Width="525">
     9     <Window.Resources>
    10         <local:SliderValue2StringConverter x:Key="s2vCvt"></local:SliderValue2StringConverter>
    11     </Window.Resources>
    12     <Grid>
    13         <Grid.ColumnDefinitions>
    14             <ColumnDefinition Width="191*"/>
    15             <ColumnDefinition Width="326*"/>
    16         </Grid.ColumnDefinitions>
    17         <Grid.RowDefinitions>
    18             <RowDefinition Height="111*"/>
    19             <RowDefinition Height="209*"/>
    20         </Grid.RowDefinitions>
    21         <StackPanel>
    22             <TextBox Name="tbx" Text="{Binding Path=Value, ElementName=sldrSlider,UpdateSourceTrigger=Explicit,Converter={StaticResource ResourceKey=s2vCvt}}" ></TextBox>
    23             <Slider Name="sldrSlider" Minimum="0" Maximum="100"></Slider>
    24             <Button Height="30" Width="100" Content="Apply" Click="Button_Click"></Button>
    25        
    26         </StackPanel>
    27         <StackPanel Grid.Column="1">
    28             <StackPanel Orientation="Horizontal">
    29                 <Label Content="R:"></Label>
    30                 <Slider Name="sldR" Foreground="Red" Width="300" Minimum="0" Maximum="255" Ticks="1"></Slider>
    31             </StackPanel>
    32             <StackPanel Orientation="Horizontal">
    33                 <Label Content="G:"></Label>
    34                 <Slider Name="sldG" Foreground="Red" Width="300" Minimum="0" Maximum="255" Ticks="1"></Slider>
    35             </StackPanel>
    36             <StackPanel Orientation="Horizontal">
    37                 <Label Content="B:"></Label>
    38                 <Slider x:Name="sldB" Foreground="Red" Width="300" Minimum="0" Maximum="255" Ticks="1"/>
    39             </StackPanel>
    40             <StackPanel Orientation="Horizontal">
    41                 <Label Content="O:"></Label>
    42                 <Slider Name="sldO" Foreground="Red" Width="300" Minimum="0" Maximum="1" Ticks="0.1" Value="0.5"></Slider>
    43             </StackPanel>
    44 
    45         </StackPanel>
    46         <Ellipse Grid.Row="1" Grid.Column="1" Stroke="Pink">
    47             <Ellipse.Resources>
    48                 <local:Rgb2ColorConverter x:Key="colorCvt"></local:Rgb2ColorConverter>
    49             </Ellipse.Resources>
    50             <Ellipse.Fill>
    51                 <MultiBinding Converter="{StaticResource colorCvt}">
    52                     <Binding ElementName="sldR" Path="Value"></Binding>
    53                     <Binding ElementName="sldG" Path="Value"></Binding>
    54                     <Binding ElementName="sldB" Path="Value"></Binding>
    55                 </MultiBinding>
    56             </Ellipse.Fill>
    57             <Ellipse.Opacity>
    58                 <Binding Path="Value" ElementName="sldO" >
    59                     
    60                 </Binding>
    61             </Ellipse.Opacity>
    62         </Ellipse>
    63     </Grid>
    64 </Window>
    View Code

    六、绑定的删除

    我们可以使用类BindingOperations中的以下函数来删除绑定

    public static void ClearAllBindings(DependencyObject target);
    public static void ClearBinding(DependencyObject target, DependencyProperty dp);

  • 相关阅读:
    soapUI完整基本测试(来自csdn)不要问为什么系列5
    final修饰符
    soapUI入门(来自taobaoQA)不要问为什么系列4
    hashmap可以用null为键值
    让sky Driver成为你的可见硬盘
    七个好习惯
    FusionCharts v3汉化(1)
    关于工作注意点的总结
    thread.sleep详解(转帖,非常形象的好文)
    在网页中嵌入任意字体的解决方案
  • 原文地址:https://www.cnblogs.com/3xiaolonglong/p/9717605.html
Copyright © 2011-2022 走看看