WPF学习之 数据绑定

数据绑定的关键是

System.Windows.Data.Binding
它会把两个属性粘在一起,并在它们之间建立一条通道。

最简单的绑定

建立一个窗体

<Window x:Class="eventCon.Window3"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="数据绑定" Height="294" Width="443">
    <Grid x:Name="xxiu">
         <TextBlock HorizontalAlignment="Left" Margin="23,100,0,0" Name="textBlock1" Width="120" Height="21" VerticalAlignment="Top" Text="{Binding Name}" />
        <TextBlock Height="21" HorizontalAlignment="Left" Margin="43,0,0,53" Name="textBlock2" VerticalAlignment="Bottom" Width="120" Text="{Binding Sex}" />
    </Grid>
</Window>

在窗体里面有两个TextBlock对象

然后创建一个数据对象

public class user
{
    public string Name
    {
        get;
        set;
    }
    public string Sex
    {
        get;
        set;
    }
}

最后我们为数据绑定建立通道

 user us = new user()
            {
                Name = "修修",
                Sex = ""

            };
 this.xxiu.DataContext = us;

这里用DataContent把数据与xxiu这个容器联系在一起,然后在xaml页面上面用Binding把数据绑定起来。运行一下

image 

这里数据绑定的步骤

1.创建数据对象 user us=new user()

2.把数据对象映射到容器,DataContext=us 。在书上这里称之为数据上下文,所有的FrameworkElement的元素都会有数据上下文DataContext这个属性。

3.为容器中的对象绑定数据 Binding Name

数据绑定模式

image

数据绑定模式有三中绑定模式

1. OneTime 一次绑定,属于绑定后就不在管的类型

2. OneWay  单向绑定,属于绑定后数据源发生变化时更新,适用于变化的数据

3. TwoWay  双向绑定,即数据在目标或数据源中都将通知对方

我们把第一个简单例子中的绑定模式设置成OneWay ,在绑定中设置Mode=OneWay

<TextBlock Margin="33,31,53,0" Name="textBlock1" Height="21" Grid.Column="0"  VerticalAlignment="Top" Text="{Binding Name,Mode=OneWay }" />
<TextBlock Height="21" Margin="42,90,44,0" Name="textBlock2" Grid.Column="0" VerticalAlignment="Top" Text="{Binding Sex,Mode=OneWay}" />
        

这样就完成了绑定模式的设置,当Mode没有设置时默认为OneWay。

这里我们发现当我们的数据源发生了变化的时候,显示并没有更新。这是为什么呢。

更改通知

为了使源对象的更改能够传播到目标,必须实现INotifyPropertyChanged接口。INotifyPropertyChanged具有PropertyChanged事件,该事件通知绑定引擎源已经更改,以便引擎可以更新目标值【MSDN】

现在我们对我们的对象实现INotifyPropertyChanged这个接口。

这里我们需要引入

using System.ComponentModel;

然后修改数据源对象

public class user:INotifyPropertyChanged
{
    private string _name;
    private string _sex;
    public event PropertyChangedEventHandler PropertyChanged;
    public string Name
    {
        get { return _name; }
        set { _name = value;
        NotifyPropertyChanged("Name");
        }
    }
    public string Sex
    {
        get { return _sex; }
        set { _sex = value;
        NotifyPropertyChanged("Sex");
        }
    }

    public void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

}

当属性发生变化时执行PropertyChanged通知值发生了变化。这样样我们在设置Mode的属性的时候就能够看到值变化的通知了

绑定到对象集合

       可以将绑定对象视为一个对象,也可以将它视为一个对象集合。比如显示一个列表,为此,需要使用ItemsControl并通过DataTemplate重复此操作,以显示集合中的每一项。

        对于从ItemsPanel派生的控件都能够显示列表集合,如ListBox,ComboBox等。他们都具有ItemsSource属性,可以直接为该属性设置集合。

比如我们为一个ComBoBox设置绑定。

     List<user> users = new List<user>(); 
     users.Add(new user(){Name = "贾宝玉", Sex = ""});
     users.Add( new user() { Name ="林黛玉",Sex =""});
     users.Add(new user() { Name = "薛宝钗", Sex = ""});

     comboBox1.ItemsSource = users;

image

数据绑定上去了,但是不是我们想要的结果。

为什么会出现这种情况呢,它是显示的对象返回的ToString()。我们可以重写这个对象的ToString。

  public override string ToString()
  {
        return string.Format("姓名:{0}性别:{1}",_name,_sex);
  }

image

但是这样并不是很好用,是很难用,我们在做WinFrom的时候有一个绑定DisplayMenber可以用来设置数据集的绑定字段。这里提供了DisplayMenberPath这个属性。

 <ComboBox Margin="42,0,44,95" Name="comboBox1" Height="23" VerticalAlignment="Bottom"  DisplayMemberPath="Name"/>

image

这样就可以得到我们想要的结果了,但是这个似乎在有些时候也不能够满足我们的需求。

这里就要用到数据模板了。通过ItemsControl控件定义数据模板。这里的数据模板和ASP.NET里面定义GridView的模板非常的相似。

<ComboBox Margin="42,0,44,95" Name="comboBox1" Height="23" VerticalAlignment="Bottom"  >
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel  Orientation="Horizontal"> 
                     <TextBlock Text="{Binding Name}"></TextBlock>
                     <TextBlock Text="{Binding Sex}"></TextBlock> 
                    </StackPanel>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>

这里我们只需要对ItemsControl.ItemTemplate 进行设置,并同时使用 DataTemplate 来定义数据对象的外观

image 

就得到我们所需要的值了,当然,我们可以把模板定义的非常有个性。

 <ComboBox Margin="42,0,44,95" Name="comboBox1" Height="23" VerticalAlignment="Bottom"  >
            <ComboBox.ItemTemplate>
                <DataTemplate> 
                    <Grid Height="60" Margin="24,0,202,12" VerticalAlignment="Bottom" Grid.ColumnSpan="2">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="28*" />
                            <RowDefinition Height="32*" />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="55*" />
                            <ColumnDefinition Width="95*" />
                        </Grid.ColumnDefinitions>
                        <Image  Grid.RowSpan="2" Margin="6,6,8,6" Name="image1" Stretch="Fill"   Source="/eventCon;component/image/1.png" />
                        <TextBlock Grid.Column="1" Margin="4,4,13,3" Name="textBlock3" Text="{Binding Name}" />
                        <TextBlock Margin="8,5,9,6" Name="textBlock4" Grid.Column="1" Grid.Row="1" Text="{Binding Sex}" />
                    </Grid>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>

image

DataGrid控件

在ASP.NET开发中常常要用到GridView控件,而做数据绑定用的最多的也是GridView控件的使用。

我们把页面上面放一个DataGrid控件,还是用上面的数据集,只是把comboBox1替换成为dataGrid1

  List<user> users = new List<user>();
            users.Add(new user() { Name = "贾宝玉", Sex = "" });
            users.Add(new user() { Name = "林黛玉", Sex = "" });
            users.Add(new user() { Name = "薛宝钗", Sex = "" });

            dataGrid1.ItemsSource = users;

image

但是这个表头并不是我们想要的,我们希望Name的地方显示“姓名” sex的地方显示“性别”,这里我们就要用到自定义列,如果对ASP.NET的熟悉这个也是很好理解的

我们给他添加两列,并指定Binding属性绑定到的列,让自动生成列为False

 <my:DataGrid AutoGenerateColumns="False" Margin="60,24,78,35" Name="dataGrid1" Background="AliceBlue" BorderBrush="Snow" Foreground="Chocolate" AlternatingRowBackground="Green" >
            <my:DataGrid.Columns>
                <my:DataGridTextColumn Header="姓名" Binding="{Binding Name}" />
                <my:DataGridTextColumn Header="性别" Binding="{Binding Sex}" />
            </my:DataGrid.Columns>
</my:DataGrid>

image

我们在做ComboBox 的时候使用了模板来显示一个很特别的格式,DataGrid中当然也是支持模板的,给DataGrid添加一个模板列,然后把在ComboBox中使用的模板拿过来用用。

<my:DataGrid AutoGenerateColumns="False" Margin="12,22,43,37" Name="dataGrid1" Background="AliceBlue" BorderBrush="Snow" Foreground="Chocolate" AlternatingRowBackground="Green" >
            <my:DataGrid.Columns>
                <my:DataGridTemplateColumn Header="人   物" Width="400">
                    <my:DataGridTemplateColumn.CellTemplate>
                        <DataTemplate >
                            <Grid Height="60" Margin="24,0,202,12" VerticalAlignment="Bottom" Grid.ColumnSpan="2">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="28*" />
                                    <RowDefinition Height="32*" />
                                </Grid.RowDefinitions>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="55*" />
                                    <ColumnDefinition Width="95*" />
                                </Grid.ColumnDefinitions>
                                <Image  Grid.RowSpan="2" Margin="6,6,8,6" Name="image1" Stretch="Fill"   Source="/eventCon;component/image/1.png" />
                                <TextBlock Grid.Column="1" Margin="4,4,13,3" Name="textBlock3" Text="{Binding Name}" />
                                <TextBlock Margin="8,5,9,6" Name="textBlock4" Grid.Column="1" Grid.Row="1" Text="{Binding Sex}" />
                            </Grid>
                        </DataTemplate>
                    </my:DataGridTemplateColumn.CellTemplate>
                    <my:DataGridTemplateColumn.CellEditingTemplate>
                        <DataTemplate />
                    </my:DataGridTemplateColumn.CellEditingTemplate>
                </my:DataGridTemplateColumn>
            </my:DataGrid.Columns> 
        </my:DataGrid>

image

到这里发现很多的东西在ASP.NET中有些类似。

原文地址:https://www.cnblogs.com/ac1985482/p/1727666.html