WPF的数据绑定之数据绑定基础(绑定到元素属性)

WPF的数据绑定之数据绑定基础(绑定到元素属性)

前路漫漫其修远兮

数据绑定可以将任何控件的任何属性绑定到其他控件的属性、对象、数据库等,在WPF中,数据绑定主要在如下所示的两个对象之间建立关系。

  • 数据源对象:WPF将从改对象中提取信息,交由目标对象进行显示。
  • 目标对象:从数据源中提取信息,并赋给该对象的属性。

C#WPF 在Binding 中Path的意思

<TextBox x:Name="txt1" />
<TextBlock x:Name="txt2" Text="{Binding Path=Text, ElementName=txt1}" />

//绑定的是名为txt1的 TextBox(控件类型)控件,但是TextBlock要显示的当然不是控件类型了,所以需要一个标示再次指定显示什么,Path就有用了,在这里表示TextBox类型控件的Text值,就是说,txt1中显示的值。
“{Binding Path=Text, ElementName=txt1}” 标示 txt1中的Text的值。

<TextBlock x:Name="txt2" Text="{Binding Path=Text, ElementName=txt1}" />

如果 txt1.Text 是“这是txt1”,txt2由于它的Text绑定了txt1.Text属性,所以txt2.Text 显示的也是“这是txt1”,而且如果txt1.Text的值变动,txt2.Text的值也变动。


绑定多个属性
XAML:其中还涉及绑定方向,绑定更新的内容,后面一一介绍

<Grid  Margin="5">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <!-- 数据源对象-->
        <Slider Name="sliderFontSize" Margin="3" Minimum="1" Maximum="40" Value="10"></Slider>
        <TextBox Name="txtContent" Margin="3" Grid.Row="1" Text="示例内容"></TextBox>
        <ListBox Margin="3" Grid.Row="2" Name="lstColors">
            <ListBoxItem Tag="Blue">蓝色</ListBoxItem>
            <ListBoxItem Tag="DarkBlue">深蓝</ListBoxItem>
            <ListBoxItem Tag="LightBlue">淡蓝</ListBoxItem>
        </ListBox>
        <!--实现多个数据源绑定,目标对象-->
        <TextBlock Margin="3" Name="lblSampleText"
                   FontSize="{Binding ElementName=sliderFontSize,Path=Value}" Grid.Row="3"
                   Text="{Binding ElementName=txtContent,Path=Text, Mode=OneWay}"
                   Foreground="{Binding ElementName=lstColors,Path=SelectedItem.Tag}"
                   >
            
        </TextBlock>
        <TextBox
            Margin="3" Name="lblSampleText2"
             FontSize="{Binding ElementName=sliderFontSize,Path=Value}" Grid.Row="4"
                   Text="{Binding ElementName=txtContent,Path=Text, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged
            }"
                   Foreground="{Binding ElementName=lstColors,Path=SelectedItem.Tag}"
            >

        </TextBox>
    </Grid>
  •  

绑定的方向,使用Mode属性指定。

  • OneWay:当源属性发生更改时更新目标属性
  • TwoWay:当源属性发生更改时更新目标属性,当目标属性发生更改时,同时也更新源属性
  • OneTime:仅当程序启动时或DataContext进行更改时更新目标属性
  • OneWayToScource:目标属性更改时更新源属性
  • Default:使用目标属性默认Mode值

绑定更新
在TwoWay模式,当目标对象发生更改时,变化不会立即被传递到数据源。这时需要定义Binding.UpdateSourceTrigger属性。

  • Default:绑定目标属性默认UpdateSourceTrigger值。多数依赖项属性的默认值为PeopertyChanged,而Text属性的默认值为LostFocus。
  • PeopertyChanged:当绑定目标属性更改时,立即更新绑定源。
  • LostFocus:当绑定目标元素失去焦点时,更新绑定源。
  • Explicit:仅在调用UpdateSource()方法时更新绑定源。
    就像上述例子一样,用到的是PeopertyChanged。
    UpdateSourceTrigger.Explicit则在用户显示地调用代码才能更新,这在一些场合是非常有用的,比如,如果希望用户一次性输入所有设定后,单击一个确定按钮,才将用户所作的改变提交并更新这种情形下。一般是调用BindingExpression.UpdateSource方法触发立即更新。
    BindingExpression封装了与绑定有关的信息。
    例子:
    XAML
 <Grid  Margin="5">
   <!-- 绑定来源-->
        <ScrollBar Name="scroll" Orientation="Horizontal" Margin="24" Maximum="100" LargeChange="10" SmallChange="1"/>
        <!-- 绑定目标-->
        <TextBox HorizontalAlignment="Center" Name="scrollfontsize" Width="200"  Height="50" Text="{Binding ElementName=scroll, Path=Value,Mode=TwoWay, UpdateSourceTrigger=Explicit}" FontSize="30" Margin="10,0,297,0" VerticalAlignment="Top"/>
        <!--应用更新按钮-->
        <Button Name="btn" Content="应用更新" Width="50" Click="btn_Click" Height="30" Margin="352,33,105,247"/>
    </Grid>

后台

private void btn_Click(object sender, RoutedEventArgs e){
     //获取应用到TextBox的BindingExpression对象
     BindingExpression binding = scrollfontsize.GetBindingExpression(TextBox.TextProperty);
     //更新ScrollBar的value属性
     binding.UpdateSource();
}

引申:[WPF]静态资源(StaticResource)和动态资源(DynamicResource)

 

绑定自定义的数据类对象

转载自https://blog.csdn.net/i1tws/article/details/67655880

在xaml代码中,Binding标记扩展中仅定义了Path属性,将它绑定到StudentData类的属性上。不需要定义源对象,因为通过指定DataContext类定义源对象。

DataContext是一个依赖属性,它用基于FramewrokElement定义。指定相应控件的DataContext属性表示当前控件中的每个元素都默认绑定此数据。

<Window x:Class="BindingDemo.Window2"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window2" Height="300" Width="300">
    <Grid>
        <!-- 简单对象的绑定 -->
        <StackPanel Name="stackPanel" HorizontalAlignment="Left" VerticalAlignment="Top" Orientation="Vertical">
            <Label Name="lbId" Content="{Binding ID}"/>
            <Label Name="lbName" Content="{Binding Name}"/>
            <Label Name="lbAge" Content="{Binding Age}"/>
        </StackPanel>
    </Grid>
</Window>

数据类

namespace BindingDemo{
    public class StudentData{
        public int ID { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }
}

隐藏代码

public partial class Window2 : Window{
        public Window2(){
            InitializeComponent();
            Init();
        }
 
        public void Init(){
            StudentData stuData = new StudentData();
            stuData.ID = 1001;
            stuData.Name = "小明";
            stuData.Age = 18;
 
            //this.DataContext = stuData;//整个窗口内的所有元素都可以绑定此数据
            stackPanel.DataContext = stuData;//仅stackPanel内的所有元素可以绑定此数据
        }
    }

以上绑定当修改数据内容时界面显示是不会更改的,要实现更改信息传递给用户界面,数据类必须实现INotifyPropertyChanged接口。

该接口定义了ProperytChanged事件,该事件在OnPropertyChagned方法中触发。

xaml代码

<Window x:Class="BindingDemo.Window2"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window2" Height="300" Width="300">
    <Grid>
        <!-- 简单对象的绑定 -->
        <StackPanel Name="stackPanel" HorizontalAlignment="Left" VerticalAlignment="Top" Orientation="Vertical">
            <Label Name="lbId" Content="{Binding ID}"/>
            <Label Name="lbName" Content="{Binding Name}"/>
            <Label Name="lbAge" Content="{Binding Age}"/>
            <Button Name="btnChang" Content="按钮" Click="btnChang_Click"/>
        </StackPanel>
    </Grid>
</Window>

数据类

namespace BindingDemo{
    public class StudentData : INotifyPropertyChanged{
        private int _id = 0;
        private string _name = "";
        private int _age = 0;
 
        public int ID { 
            get { return _id; } 
            set { 
                _id = value;
                OnPropertyChanged("ID");
            } 
        }
        public string Name{
            get { return _name; }
            set  { 
                _name = value;
                OnPropertyChanged("Name");
            }
        }
        public int Age {
            get { return _age; }
            set { 
                _age = value;
                OnPropertyChanged("Age");
            }
        }
 
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName){
            if(PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

隐藏代码
    public partial class Window2 : Window
    {
        public Window2()
        {
            InitializeComponent();
 
            Init();
        }
 
        private StudentData stuData;
        public void Init()
        {
            stuData = new StudentData();
            stuData.ID = 1001;
            stuData.Name = "小明";
            stuData.Age = 18;
 
            //this.DataContext = stuData;//整个窗口内的所有元素都可以绑定此数据
            stackPanel.DataContext = stuData;//仅stackPanel内的所有元素可以绑定此数据
        }
 
        private void btnChang_Click(object sender, RoutedEventArgs e)
        {
            stuData.ID = 1002;
            stuData.Name = "小红";
            stuData.Age = 17;
        }
    }

此时运行程序点击按钮更改信息时发现用户界面显示的数据也跟着刷新了。下面的内容是对上面的数据类做的进一步封装。最终效果是一样的。


先创建一个实现INotifyPropertyChanged接口的一个抽象类基类BindableObject,数据类只需要继承此抽象基类自然就实现了接口INotifyPropertyChanged

namespace BindingDemo
{
    public abstract class BindableObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
 
        protected void SetProperty<T>(ref T item,T value,[CallerMemberName] string propertyName=null)
        {
            if(!EqualityComparer<T>.Default.Equals(item,value))
            {
                item = value;
                OnPropertyChanged(propertyName);
            }
        }
    }
}


namespace BindingDemo
{
    public class StudentData : BindableObject
    {
        private int _id = 0;
        private string _name = "";
        private int _age = 0;
 
        public int ID 
        { 
            get { return _id; } 
            set 
            { 
                SetProperty(ref _id,value);
            } 
        }
        public string Name
        {
            get { return _name; }
            set 
            {
                SetProperty(ref _name, value);
            }
        }
        public int Age 
        {
            get { return _age; }
            set 
            {
                SetProperty(ref _age, value);
            }
        }
    }
}


[CallerMemberName]获取调用方的属性或方法名称

EqualityComparer<T>    T为要比较的对象的类型

EqualityComparer<T>.Default  返回一个默认的相等比较器,用于比较此泛型自变量指定的类型。

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值