`
wangleifire
  • 浏览: 510860 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

关于WPF ListView数据绑定 入门 及分类,排序

    博客分类:
  • c#
阅读更多

不多说,先直接上代码

  1. public   class  Student : INotifyPropertyChanged  
  2. {  
  3.     public   event  PropertyChangedEventHandler PropertyChanged;  // 这个接口仅包含一个事件而已   
  4.   
  5.     private   int  id;  
  6.     public   int  Id  
  7.     {  
  8.         get  {  return  id; }  
  9.         set   
  10.         {  
  11.             id = value;  
  12.             if  ( this .PropertyChanged !=  null )  
  13.             {  
  14.   
  15.                 this .PropertyChanged.Invoke( this new  PropertyChangedEventArgs( "Id" ));  // 通知Binding是“Id”这个属性的值改变了   
  16.             }  
  17.         }  
  18.     } 
  19. }

public class Students :  ObservableCollection<Student>

{

}

 

<Window.Resource>

   <local:Students x:Key="Students">

      <local:Student Id="111" />

      <local:Student Id="222" />

  </local:Students>

</Window.Resource>

<ListView ItemsSource="{StaticResource Students}">

   <ListView.ItemTemplate>

      <DataTemplate>

          <TextBox Text="{Binding Path=Id}" />

      </DataTemplate>

   </ListView.ItemTemplate>

</ListView>

 

 

 

 

再来看看别人文章,里面有如何分类,排序的方法,仔细看哟!

 

1 Binding to List Data

前面都是绑定到一个对象,下面我们学习绑定到对象列表的方法。

我们还是先组织要绑定的数据,对象所对应的类还是Person,但新增了一个新类People,该类用来组织Person的列表.代码如下:

using 
System;
            using 
System.Collections.Generic;
            using 
System.ComponentModel;//INotifyPropertyChanged
            
namespace 
SimpleDataBinding
            {
            class 
Person 
: INotifyPropertyChanged
            
{
            public event 
PropertyChangedEventHandler 
PropertyChanged;
            protected void 
Notify(string 
PropName)
            {
            if 
(this
.PropertyChanged != null
)
            {
            PropertyChanged(this
, new 
PropertyChangedEventArgs
(PropName));
            }
            }
            public 
Person()
            {
            _Age = 0;
            _name = "Null"
;
            this
.CurrentDate = DateTime
.Now;
            }
            private string 
_name;
            public string 
Name
            {
            get 
{ return 
_name; }
            set
            
{
            if 
(value 
== _name)
            { return
; }
            _name = value
;//注意:不能用this.Name来赋值,如果这样形成循环调用,栈溢出
            
Notify("Name"
);
            }
            }
            private int 
_Age;
            public int 
Age
            {
            get 
{ return 
_Age; }
            set
            
{
            if 
(value 
== _Age) return
;
            _Age = value
;
            Notify("Age"
);
            }
            }
            public 
DateTime 
CurrentDate { get
; set
; }
            }
             
//People类
            
class 
People 
: List
<Person
>
            {
            }


            }
            

注意在同一命名空间下的代码最后添加了Perople类。

我们在UI里显示的XAML如下:

<
Window 
x
:
Class
="ListDataBinding.BindListDataTest"
            
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            
xmlns
:
x
="http://schemas.microsoft.com/winfx/2006/xaml"
              


xmlns
:
src



="clr-namespace:ListDataBinding"



            
Title
="BindListDataTest" 
Height
="113" 
Width
="300">
            <
Window.Resources
>
             <


src
:
People 
x
:
Key


="Family">


            <
src
:
Person 
Name
="Jack" 
Age
="18"/>
            <
src
:
Person 
Name
="Tom" 
Age
="30"/>
            <
src
:
Person 
Name
="Jone" 
Age
="14"/>
            <
src
:
Person 
Name
="Rose" 
Age
="17"/>
            <
src
:
Person 
Name
="Mike" 
Age
="13"/>
            </
src
:
People
>
            </
Window.Resources
>
            <
Grid 
DataContext
="{
StaticResource 
Family
}">
            <
Grid.RowDefinitions
>
            <
RowDefinition
/>
            <
RowDefinition
/>
            </
Grid.RowDefinitions
>
            <
Grid.ColumnDefinitions
>
            <
ColumnDefinition 
Width
="80"/>
            <
ColumnDefinition 
Width
="*"/>
            </
Grid.ColumnDefinitions
>
            <
TextBlock 
Grid.Row
="0" 
Grid.Column
="0" 
Text
="Name" 
TextAlignment
="Center" 
VerticalAlignment
="Center"/>
            <
TextBlock 
Grid.Row
="1" 
Grid.Column
="0" 
Text
="Age" 
TextAlignment
="Center" 
VerticalAlignment
="Center"/>
            <
TextBox 
Grid.Row
="0" 
Grid.Column
="1" 
Name
="txtName" 
Text
="{
Binding 
Path


=Name}"

 />
            <
TextBox 
Grid.Row
="1" 
Grid.Column
="1" 
Name
="txtAge" 
Text
="{
Binding 
Path


=Age}"/

>
            </
Grid
>
            </
Window
>
            

我们发现这样的UI只能显示第一个数据项目,也就是说列表的当前项为0,至于其他的就无法显示出来了。

如果要显示其他的只有可通过如下代码的方式来取(注意:书中代码似乎有问题):

private void 
btnNext_Click(object 
sender, RoutedEventArgs 
e)
            {
            People 
people = (People
)this
.FindResource("Family"
);
            txtName.Text = people[1].Name;
            txtAge.Text = people[1].Age.ToString();
            }

 

1.1当前项Current Item

取得当前项

可以通过上面的方法取得当前项,当然我们更专业的做法还是使用Collection View

还是代码说明比较简洁:

People 
people = (People
)this
.FindResource("Family"
);
            ICollectionView 
view = CollectionViewSource
.GetDefaultView(people);
            Person 
peron = (Person
)view.CurrentItem;

注意:ICollectionView在System.ComponentModel命名空间里。

导航当前项

还是代码来说明更合适点:

      private 
ICollectionView 
GetView()
            {
            People 
people = (People
)this
.FindResource("Family"
);
            ICollectionView 
view = CollectionViewSource
.GetDefaultView(people);
            return 
view;
            }
            private void 
btnNext_Click(object 
sender, RoutedEventArgs 
e)
            {
            ICollectionView 
view = GetView();
            view.MoveCurrentToNext();
            if 
(view.IsCurrentAfterLast)
            {
            view.MoveCurrentToLast();
            }
            }
            private void 
btnPrior_Click(object 
sender, RoutedEventArgs 
e)
            {
            ICollectionView 
view = GetView();
            view.MoveCurrentToPrevious();
            if 
(view.IsCurrentBeforeFirst)
            {
            view.MoveCurrentToFirst();
            }
            }
1.2 List Data Targets

我们将列表数据绑定到类似TextBox这样的控件难以很好地展现列表数据。我们考虑ListBox控件来列举多个数据信息。

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

这时的效果如下:列表确实显示了所有对象的信息,因为我们没有设置Path属性,所以采用默认的Convertation来处理,显示对象 类型。同时一定要注意使用IsSynchronizatizedWithCurrentItem=True,这样才能列表信息与其他信息同步。但究竟如何 才能更好地表达我们需要的信息呢,请参看下一节:

clip_image002

1.3 Display Members, Value Members, and Look-Up Bindings

代码示例也许更易理解:

<
ListBox 
Grid.Row
="3" 
Grid.Column
="1" 
Name
="lstbox" 
ItemsSource
="{
Binding
}"
            
DisplayMemberPath
="Name" 
SelectedValuePath
="Age" 
IsSynchronizedWithCurrentItem
="True"/>
            <
Button 
Grid.Row
="4" 
Grid.Column
="0" 
Name
="btnShowValue" 
Content
="ShowValue" 
Click
="btnShowValue_Click" />
private void 
btnShowValue_Click(object 
sender, RoutedEventArgs 
e)
            {
            MessageBox
.Show(lstbox.SelectedValue.ToString());
            }
1.4数据模板Data Templates

这是利用ListBox控件有一个ItemTemplate属性下面,他可以接受一个DataTemplate类实例,

该模板可以重复绑定到ListBox的每一个项目元素,注意DataTemplate只能指定一个孩子节点,所以一般使用容器控件来组织下面的布局。

<
ListBox 
Grid.Row
="3" 
Grid.Column
="1" 
Name
="lstbox" 
ItemsSource
="{
Binding
}">
            <
ListBox.ItemTemplate
>
            <
DataTemplate
>
            <
TextBlock 
Text
="{
Binding 
Path
=Name}">
            
的年龄是
<
TextBlock 
Text
="{
Binding 
Path
=Age}"></
TextBlock
>
            </
TextBlock
>
            </
DataTemplate
>
            </
ListBox.ItemTemplate
>
            </
ListBox
>
我本人不赞同书中这样的做法,添加一个StackPanel更舒服点。

 

1.5 列表改变List Changes

当我们改变列表的数据的时候,却出现如下现象:

image

只是因为我们需要绑定的列表需要实现INotifyCollectionChanged接口:

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

 

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

欢呼雀跃吧,我们改变上面例题的代码,一切如我们想象的美好。

所有的一切就如此简单,简单代码改动:

//People类
            
class 
People 
: ObservableCollection


<Person
>
            {
            }

clip_image002[4]

1.6 排序Sorting

简单的代码还是足以繁杂的文字,让我们看如下方法:

       private void 
btnSort_Click(object 
sender, RoutedEventArgs 
e)
            {
            ICollectionView 
view = GetView();
            if 
(view.SortDescriptions.Count == 0)
            {
            view.SortDescriptions.Add(new 
SortDescription
("Name"
, ListSortDirection
.Ascending));
            view.SortDescriptions.Add(new 
SortDescription
("Age"
, ListSortDirection
.Descending));
            }
            else
            
{
            view.SortDescriptions.Clear();
            }
            }

当然我们还可以自定义排序方式:

    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 != 0) return 
nameCompare;
            return 
rhs.Age - lhs.Age;
            }
            }

注意:WPF不使用System.Collection.Generic命名空间的泛型IComparer接口,而是使用System.Collection的。呵呵。

使用代码如下:

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

注意:ListCollectionView支持自定义和排序,其他的不支持。

1.7 集合缺省视图类型Default Collection View

image

1.8 过滤 Filter

依然是我熟悉的表达方式:代码:

       private void 
btnFilter_Click(object 
sender, RoutedEventArgs 
e)
            {
            ListCollectionView 
view = (ListCollectionView
)GetView();
            if 
(view.Filter == null
)
            {
            view.Filter = delegate
(object 
item)
            {
            return 
((Person
)item).Age > 17;
            };
            }
            else
            
{
            view.Filter = null
;
            }
            }
1.9 分组Grouping

分组的意思大家很明白就是按照某一个或几个关键属性进行分类。

进行分组很简单和sort类似,只需要以下几行代码:

          ICollectionView 
view = GetView();
            if 
(view.GroupDescriptions.Count == 0)
            {
            view.GroupDescriptions.Add(new 
PropertyGroupDescription
("Age"
));
            }
            else
            
{
            view.GroupDescriptions.Clear();
            }

但这在UI层面并没有任何影响,这需要我们对ItemsControl类的控件(例如ListBox)设置GroupStyle属性,GroupStyle类缺省地提供了一个静态的属性实现,我们可以如下设置:

      <
ListBox 
Grid.Row
="3" 
Grid.Column
="1" 
Name
="lstbox" 
ItemsSource
="{
Binding
}"  
IsSynchronizedWithCurrentItem
="True">
            <


ListBox.GroupStyle


>
            <
x
:
Static 
Member


="GroupStyle.Default"/>
            </
ListBox.GroupStyle


>


            <
ListBox.ItemTemplate
>
            <
DataTemplate
>
            <
TextBlock 
Text
="{
Binding 
Path
=Name}">
            
的年龄是
<
TextBlock 
Text
="{
Binding 
Path
=Age}"></
TextBlock
>
            </
TextBlock
>
            </
DataTemplate
>
            </
ListBox.ItemTemplate
>
            </
ListBox
>

但也许这并不是我们所喜欢的界面,简单得让人生厌,还好微软提供了这个对象的一个属性:HeaderTemplate用于定义分组的栏目的外观,微软总是为大家想得那么周到,养活那么多天才是需要钱的,希望大家不要老是讲微软的坏话。

           <
ListBox.GroupStyle
>
            <
GroupStyle
>
            <
GroupStyle.HeaderTemplate
>
            <
DataTemplate
>
            <
StackPanel 
Background
="Green"  
Orientation
="Horizontal">
            <
TextBlock 
Text
="{
Binding 
Name
}"/>
            <
TextBlock 
Text
="("/>
            <
TextBlock 
Text
="{
Binding 
ItemCount
}"/>
            <
TextBlock 
Text
=")"/>
            </
StackPanel
>
            </
DataTemplate
>
            </
GroupStyle.HeaderTemplate
>
            </
GroupStyle
>
            </
ListBox.GroupStyle
>

有这模板属性一切由你发挥,真是好也,然而即使这样解决了UI问题,但是如果我们还希望更进一步,能否实现范围内分组呢?呵呵,然也:

这时我们不需要去想着如何继承GroupStyle类,而是采用围魏救赵的方式,定义一个IValueConverter,

   public class 
AgeRangeConvert 
: IValueConverter
            
{
            public object 
Convert(object 
value, Type 
targetType, object 
parameter, CultureInfo 
culture)
            {
            int 
_value = (int
)value;
            if 
(_value <= 10)
            return 
"10岁以下"
;
            else if 
(_value <= 20)
            return 
"20岁以下"
;
            else
            return 
"20岁以上"
;
            }
            public object 
ConvertBack(object 
value, Type 
targetType, object 
parameter, CultureInfo 
culture)
            {
            throw new 
NotImplementedException
();
            }
            }

简单调整前面分组代码:

           ICollectionView 
view = GetView();
            if 
(view.GroupDescriptions.Count == 0)
            {
            view.GroupDescriptions.Add(new 
PropertyGroupDescription
("Age"
,new  
AgeRangeConvert
()));
            }
            else
            
{
            view.GroupDescriptions.Clear();
            }

一切搞定,享受成果吧:

image

既然GroupDescripions是个集合类型,我们不妨看下面代码究竟是什么效果:

            ICollectionView 
view = GetView();
            if 
(view.GroupDescriptions.Count == 0)
            {
            view.GroupDescriptions.Add(new 
PropertyGroupDescription
("Age"
,new  
AgeRangeConvert
()));
            view.GroupDescriptions.Add(new 
PropertyGroupDescription
("Age"
));
            }
            else
            
{
            view.GroupDescriptions.Clear();
            }

运行如下:

clip_image002[1]

呵呵,这不正是有时你需要的效果吗?至于界面如何优化,模板如何定义更好看我们以后话题再说。

分享到:
评论

相关推荐

    WPF后台动态绑定ListView数据源

    这将帮助开发者更好地理解WPF中的数据绑定和ListView的使用。 首先,`ListView`的数据源通常是通过`ItemsSource`属性来设置的。在WPF中,数据绑定是核心特性之一,它允许UI元素与数据模型之间的交互。你可以将任何...

    wpf列表listview自动排序排列

    1. **数据绑定**:首先,将数据源绑定到`ListView`的`ItemsSource`属性。例如,如果你有一个名为`items`的`ObservableCollection`,你可以这样做: ```xml &lt;ListView ItemsSource="{Binding items}"&gt; ``` 2. **...

    WPF ListView排序功能

    以下将详细讲解WPF ListView排序的基本概念、实现方式及相关的编程技巧。 1. **ListView的基础知识** - **数据绑定**:WPF中的ListView依赖于数据绑定来显示数据。它通过ItemsSource属性与数据源关联,可以是...

    wpf listview 滚动条和自动排序

    在Windows Presentation Foundation (WPF) 中,ListView是一个常用的控件,用于展示数据集合,并提供了丰富的定制功能。在本文中,我们将深入探讨如何处理ListView的滚动条以及实现自动排序功能。 首先,让我们关注...

    C#-WPF ListView实现可编辑数据项

    5. **数据绑定和INotifyPropertyChanged**:确保你的数据模型类实现了INotifyPropertyChanged接口,这样当属性值改变时,ListView能够自动更新视图。 ```csharp public class YourDataType : ...

    WPF ListView控件添加排序功能

    在Windows Presentation Foundation (WPF) 中,ListView 是一个强大的数据展示控件,它允许开发者以多种视图形式显示数据,并提供了丰富的自定义能力。在实际应用中,我们常常需要为ListView添加排序功能,以便用户...

    WPF ListView 漂亮样式

    通过定义GridViewColumn,我们可以指定列的标题、宽度和数据绑定。例如: ```xml &lt;ListView.View&gt; 名称" DisplayMemberBinding="{Binding Name}" /&gt; 年龄" DisplayMemberBinding="{Binding Age}" /&gt; &lt;/...

    WPF 在listview中如何实现Combobox的下拉菜单绑定Demo

    3. **Binding**:WPF的数据绑定机制,使得UI元素的属性与后台数据模型的属性之间建立连接。 4. **ObservableCollection**:一种动态数据集,当其内容发生改变时,能够通知绑定到它的对象。 实现步骤如下: 1. **...

    WPF_ListView边框_每条颜色_数据绑定_多选择_字段可拖拽

    在本文中,我们将深入探讨基于WPF(Windows Presentation Foundation)技术的ListView控件,特别是针对标题和描述中提及的关键特性,包括边框设置、每条记录的颜色定制、数据绑定、多选择以及字段拖拽功能。...

    C#中WPF ListView绑定数据的实例详解

    C#中WPF ListView绑定数据的实例详解 WPF中ListView用来显示数据十分方便, 我们可以将它分成几个列,每一个列用来显示一条数据,但是又是在一方之中。 那么怎样实现这样的效果的呢,这就要用绑定了。 我们先来看...

    wpf listView分组排序

    -- 数据绑定到ItemsSource --&gt; &lt;/ListView&gt; ``` 接下来,我们讨论排序。在WPF中,可以通过设置`CollectionView`的`SortDescriptions`属性来对ListView的数据进行排序。`CollectionView`是数据源的一个视图,它可以...

    WPF TreeView ListView 数据联动

    C#+WPF 支持模仿Tab+控件区域的设计和动态切换 支持TreeView动态修改数据 支持ListView动态修改数据,选定行变色,单个cell规则,支持Cell按钮, 支持xml解析,支持登录界面权限控制, 三层树形数据提供给TreeView ...

    WPF ListView控件中CheckBox全选联动

    在WPF应用开发中,ListView控件是一种常用的数据显示控件,它可以用来展示各种类型的数据集合。在实际项目中,我们经常需要实现一个功能,即在ListView中加入CheckBox,让用户能够通过一个主CheckBox来控制所有子项...

    解决wpf ListView最小列宽问题

    在Windows Presentation Foundation (WPF) 中,ListView 是一个强大的数据展示控件,它允许我们以网格形式显示数据,类似于Windows中的资源管理器。然而,在实际应用中,我们可能会遇到一个常见的问题,即如何设置...

    wpf5种数据绑定方式示范

    在Windows Presentation Foundation (WPF) 中,数据绑定是将用户界面(UI)元素与应用程序的数据模型连接起来的关键机制。这使得UI可以动态地反映数据的变化,反之亦然。本示例将详细介绍WPF中的五种数据绑定方式:...

    WPF中ListView添加CheckBox列

    在Windows Presentation ...总之,在WPF的ListView中添加CheckBox列涉及数据模型的设计、数据绑定、以及UI模板的创建。理解这些概念并能灵活运用,将使你能够在WPF应用程序中构建出交互性强、用户体验良好的用户界面。

    WPF简单数据绑定demo

    在Windows Presentation Foundation(WPF)中,数据绑定是一种强大的机制,它允许UI元素与应用程序的数据模型之间进行自动同步。这个“WPF简单数据绑定demo”是专为新手设计的,旨在帮助初学者快速掌握这一核心概念...

    WPF UI数据绑定

    **WPF UI数据绑定** Windows Presentation Foundation (WPF) 是微软.NET Framework的一部分,它提供了一种强大的用户界面(UI)开发框架。其中,数据绑定是WPF中的核心特性,允许UI元素与应用程序中的数据源进行...

Global site tag (gtag.js) - Google Analytics