• WPF笔记(4.3 集合数据绑定)——Data Binding


    本节介绍如何绑定一数据集合。

    1.CurrentItem
    将上节的Person聚集为泛型People类:
        public class People : List<Person>
        

        
        }

    XAML文件相应为:
    <Window x:Class="TestDataBind.Window1"
        xmlns
    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x
    ="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local
    ="clr-namespace:TestDataBind" 
        Title
    ="TestDataBind" Height="300" Width="300"
        
    >
        
    <Window.Resources>
            
    <local:People x:Key="Family">
                
    <local:Person Name="Melissa" Age="36" />
                
    <local:Person Name="Tom" Age="9" />
                
    <local:Person Name="John" Age="11" />
            
    </local:People>
        
    </Window.Resources>
        
    <Grid DataContext="{StaticResource Family}" Name="grid1">
            
    <TextBlock>Name:</TextBlock>
            
    <TextBox Name="nameTextBox" Text="{Binding Path=Name}" ></TextBox>
            
    <TextBlock>Age:</TextBlock>
        
    <TextBox Name="ageTextBox" Text="{Binding Path=Age}"></TextBox>
      
    </Grid>
    </Window>


    注意,这次Grid绑定的是Famliy这个集合对象,因为只有一个TextBox,所以默认显示第一项"Melissa"。

    页面导航技术:

    2.绑定到数据列表控件

        <ListBox  ItemsSource="{Binding}"  IsSynchronizedWithCurrentItem="True"  />

    没有Path属性,意为绑定到当前的所有对象。
    ItemsSource属性设为"{Binding}",不用设置具体是哪一个Source,默认为找到的第一个数据源。
    IsSynchronizedWithCurrentItem属性设置为True,保证了自身选项变化,其他绑定控件也相应跟着改变。

    运行如下图,可以看到,显示的并不是我们需要的数据,而是直接把每个Object的Type输出了。

    3.数据模板
    如上所示,我们要显示出正确的数据列表。这个很像GridView或DataList中的数据模板。具体设置如下:

    <ListBox  ItemsSource="{Binding}">
      
    <ListBox.ItemTemplate>
        
    <DataTemplate>
          
    <StackPanel Orientation="Horizontal">
            
    <TextBlock TextContent="{Binding Path=Name}" />
            
    <TextBlock TextContent=" (age: " />
            
    <TextBlock
              TextContent
    ="{Binding Path=Age}"
              Foreground
    ="
                {Binding
                  Path
    =Age,
                  Converter
    ={StaticResource AgeToForegroundConverter}}" />
            <TextBlock TextContent=")" />
          
    </StackPanel>
        
    </DataTemplate>
      
    </ListBox.ItemTemplate>
    </ListBox>

    这里我们使用了ListBox.ItemTemplate属性,这个属性接受一个DataTemplate对象。该对象里面的绑定方式同4.2中介绍的方法。

    当然,我们可以把绑定部分放入Resource,这样,ListBox就简单了。
    <Window.Resources>
     
    <local:People x:Key="Family"></local:People>
      
    <DataTemplate DataType="{x:Type local:Person}">
        
    <StackPanel Orientation="Horizontal">
          
    <TextBlock TextContent="{Binding Path=Name}" />
          
    <TextBlock TextContent=" (age: " />
          
    <TextBlock TextContent="{Binding Path=Age}"  />
          
    <TextBlock TextContent=")" />
        
    </StackPanel>
      
    </DataTemplate>
    </Window.Resources>

    <!-- no need for an ItemTemplate setting -->
    <ListBox ItemsSource="{Binding}" >

    4.修改数据集合

    以Add为例,这么写是不对的,因为数据源根本不知道有改动:

      void addButton_Click(object sender, RoutedEventArgs e) {
        People people 
    = (People)this.FindResource("Family");
        people.Add(
    new Person("Chris"35));
      }

    WPF为集合提供了一个ObservableCollection<T>类:

    namespace System.Windows.Data {
      
    public class ObservableCollection<T> :
        Collection
    <T>, INotifyCollectionChanged, INotifyPropertyChanged {
        
      }
    }

    以及使用INotifyPropertyChanged接口:

    namespace System.Collections.Specialized {
      
    public interface INotifyCollectionChanged {
        
    event NotifyCollectionChangedEventHandler CollectionChanged;
      }
    }

    要让Person类实现INotifyPropertyChanged接口,People类继承ObservableCollection<Person>,就可以了:

    namespace PersonBinding {
      
    class Person : INotifyPropertyChanged {}
      
    class People : ObservableCollection<Person> {}
    }

    5.排序

    我们在前面使用到了ICollectionView接口view,可以对其进行排序,每种排序规则都是一个SortDescription对象:

        ICollectionView view = GetFamilyView(  );
        
    if( view.Sort.Count == 0 ) {
          view.Sort.Add(
            
    new SortDescription("Name", ListSortDirection.Ascending));
          view.Sort.Add(
            
    new SortDescription("Age", ListSortDirection.Descending));
        }
        
    else {
          view.Sort.Clear(  );   //这里将当前的排序规则清除,使用之前的排序规则
        }

    实现IComparer接口的Compare(x, y)方法,可以自定义排序类,并赋给view的CustomSort属性:
        public class PersonSorter : IComparer
        {
            
    public int Compare(object x, object y)
            {
                Person lhs 
    = (Person)x;
                Person rhs 
    = (Person)y;

                
    // Sort Name ascending and Age descending
                int nameCompare = lhs.Name.CompareTo(rhs.Name);
                
    if (nameCompare != 0return nameCompare;
                
    return rhs.Age - lhs.Age;
            }
        }

        
    public partial class Window1 : Window
        {
            ICollectionView GetFamilyView()
            {
                People people 
    = (People)this.FindResource("Family");
                
    return BindingOperations.GetDefaultView(people);
            }

            
    void sortButton_Click(object sender, RoutedEventArgs e)
            {
                ListCollectionView view 
    = (ListCollectionView)GetFamilyView();
                
    if (view.CustomSort == null)
                {
                    view.CustomSort 
    = new PersonSorter();
                }
                
    else
                {
                    view.CustomSort 
    = null;
                }
            }
        }

    这时候,我们使用的是ListCollectionView,而不再是ICollectionView。ListCollectionView是WPF提供的类,已经实现了ICollectionView接口。

    6.Filter

    WPF使用Delegate来完成数据过滤功能。
        ICollectionView view = GetFamilyView(  );
        
    if( view.Filter == null ) {
           view.Filter 
    = delegate(object item) {
            
    return ((Person)item).Age >= 18;
          };
        }
        
    else {
          view.Filter 
    = null;
        }

    这样就找到大于18岁的所有人——那个item对象很神奇的。


  • 相关阅读:
    新世纪五笔字根实例
    7 天学会新世纪五笔——原来五笔是个拼字游戏
    Ubuntu 上安装使用 ibus-rime(超实用)
    Linux 上安装最新版 Brave Browser
    安装使用 GoldenDict 查词神器 (Windows/Mac/Linux)
    1.2-Physical Ergonomics
    Django
    前端
    python一些简单的入门知识
    触发器、函数、存储过程、视图
  • 原文地址:https://www.cnblogs.com/Jax/p/884873.html
Copyright © 2020-2023  润新知