zoukankan      html  css  js  c++  java
  • 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的内容远不止这些,会在后面的博客中展现。

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

  • 相关阅读:
    游戏研发流程与构成要素
    Unity获取游戏对象详解
    Unity3D一些基本的概念和一些基本操作
    2019年Unity3D游戏开发前景预测及总结
    Unity3d游戏代码保护
    spring boot快速入门 6: 表单验证
    spring boot快速入门 5: 事务管理
    spring boot快速入门 4: jpa数据库操作 实现增删改查
    spring boot快速入门 3: controller的使用
    spring boot快速入门 2 :属性配置
  • 原文地址:https://www.cnblogs.com/yang-fei/p/4715175.html
Copyright © 2011-2022 走看看