精华内容
参与话题
问答
  • WPF 数据绑定Binding

    2019-10-01 21:17:04
    Windows Presentation Foundation (WPF) 数据绑定为应用程序提供了一种简单而一致的方法来显示数据以及与数据交互。 通过数据绑定,您可以对两个不同对象的属性值进行同步。——MSDN 什么意思呢?先可以这样理解...

    什么是数据绑定?

    Windows Presentation Foundation (WPF) 数据绑定为应用程序提供了一种简单而一致的方法来显示数据以及与数据交互。

    通过数据绑定,您可以对两个不同对象的属性值进行同步。——MSDN

     什么意思呢?先可以这样理解,数据绑定是一种行为,这个行为可以将多个对象的属性显示在UI上,当用户修改了UI上的值之后(当然必须是要看实际情况),对应的属性值也被改变,从而达到数据交互的目的。看一下MSDN上的一幅图(感觉这幅图到处都能看见(偷笑)):

    Binding可以通过XAML语句实现界面与数据的耦合。如果把Binding比作数据的桥梁,那么它的两端分别是Binding的绑定目标和绑定源。数据从哪里来哪里就是源,Binding是架在中间的桥梁,Binding目标是数据要往哪儿去。一般情况下,绑定源是逻辑层的对象,绑定目标是UI层的控件对象,这样,数据就会源源不断通过Binding送达UI层,被UI层展现,也就完成了数据驱动UI的过程。——参考《WPF中的数据绑定

    从上图可以看出数据绑定的4个组件,为方便理解,结合例子:将TextBox的内容绑定到Employee对象的Name属性,也就是说把Name的值显示在TextBox上:

    1. 绑定目标对象TextBox
      绑定目标对象可以是所有UIElement对象。为什么?这是自然而然的事情。数据绑定就是为了将数据与UI进行交互,那么绑定的这种行为必然正对所有UIElement对象,例如常见的Button,TextBlock等等。
    2. 目标属性:TextBox的Text属性
    3. 目标属性必须是依赖项属性。为什么呢?在WPF中,只有这样的属性才支持数据绑定,这也就意味着不能绑定字段。不过,在WPF中UIElemnt对象的大部分属性都是依赖属性且大多数依赖属性都是支持数据绑定的。为什么呢?从《WPF依赖属性》中可以知道,只有DependencyObject类型可以定义依赖项属性,而所有UIElement对象都是从DependencyObject派生的。
    4. 绑定源对象:Employee对象

      绑定源的对象可以有哪些呢?WPF支持CLR对象和XML形式的数据:UIElement、任何列表对象、与ADO.NET数据或Web服务关联的CLR对象、包含XML数据的XmlNode.

    5. 绑定源值的path(这个从图中看不出来,但可以想象的出来,^_^):Name

    如何绑定?

    根据实际应用的情况,绑定目标基本上都是UI对象,我们来看一下绑定数据的各种情况:

    1、绑定UI对象
    举一个简单例子,选择ComboBox下拉列表中的性别,并显示在TextBlock中。

    xaml:

    <StackPanel Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
        <TextBox x:Name="tbk"  Width="100" Height="40" Background="#FFF2F2F2" VerticalAlignment="Top"  TextAlignment="Center" FontSize="24"
                     Text="{Binding ElementName=combo,Path=SelectedItem.SexName}"/>
        <ComboBox x:Name="combo"  Width="100" Height="30" Margin="10" 
                          DisplayMemberPath="SexName" SelectedValuePath="SexId" SelectedIndex="1"/>
    </StackPanel>

    cs,主要是给ComboBox赋数据源:

        public partial class MainWindow : Window
        {
            List<SexType> _sexCollection;
            public MainWindow()
            {
                InitializeComponent();
                _sexCollection = new List<SexType>()
                {
                    new SexType(){SexId=1,SexName=""},
                    new SexType(){SexId=2,SexName=""},
                    new SexType(){SexId=3,SexName="未知"}
                };
                combo.ItemsSource = _sexCollection;
            }
        }
    
        public class SexType
        {
            public int SexId { get; set; }
            public string SexName { get; set; }
        }

    由上述例子可以看出,绑定目标:TextBox,目标属性:TextBox.Text,绑定源对象:combo,绑定源值的Path:combo.SelectedItem.SexName.个中滋味可以自行感受。

     

    2、上面这个例子中comboBox的数据源是在cs中通过”combo.ItemsSource=数据源“来赋值的,那么是否可以通过绑定数据的方式来赋值呢?答案必须是肯定的。

    我们知道ComboBox和ListBoxItem都是ItemsControl的派生类,而对于所有的ItemsControl对象都有一个ItemsSource的依赖属性。ItemsSource的类型是IEnumerable,所以集合类型可以成为它绑定的对象。

    <ComboBox x:Name="combo"  Width="100" Height="30" Margin="10" 
                          DisplayMemberPath="SexName" SelectedValuePath="SexId" SelectedIndex="1"
                          ItemsSource="{Binding _sexCollection}"/> 

    在修改一下cs文件:

        public partial class MainWindow : Window
        {
            public List<SexType> _sexCollection;
            public MainWindow()
            {
                InitializeComponent();
                _sexCollection = new List<SexType>()
                {
                    new SexType(){SexId=1,SexName=""},
                    new SexType(){SexId=2,SexName=""},
                    new SexType(){SexId=3,SexName="未知"}
                };
                //combo.ItemsSource = _sexCollection;
            }
        }

    可以看到是没有数据源的,也就是说根本就没有把数据绑到ComboBox上:

    这是为什么呢?依赖属性内的垂直通知功能让UI对相间的绑定可以自己负责同步处理,但是对于.NET集合或对象来讲,就不具备这样的能力了。为了让目标属性与源目标保持同步,源目标必须实现一个叫INotifyPropertyChanged的接口。

     

    通常我们只需将集合继承于ObservableCollection类即可。

     

     

     

     

    2、绑定集合

    3、数据模板

    4、为绑定添加规则及转换器

    如何绑定不同的源。

     

    转载于:https://www.cnblogs.com/YunGy/p/5048349.html

    展开全文
  • WPF Binding数据绑定)的用法

    万次阅读 2019-05-20 22:37:20
    1、Data Binding作用:Data BindingWPF系统中起到数据高速公路的作用,有了这条高速公路,加工好的数据会自动送达到用户界面加以显示,被用户修改过的数据也会自动回传逻辑层。 数据绑定就是将数据和图形用户界面...

    一、基本知识

    1、Data Binding作用:Data Binding在WPF系统中起到数据高速公路的作用,有了这条高速公路,加工好的数据会自动送达到用户界面加以显示,被用户修改过的数据也会自动回传逻辑层。

    数据绑定就是将数据和图形用户界面(GUI)上的控件元素关联起来,起到用户可以通过用户界面上的控件元素对数据进行操作的目的。传统的数据绑定是后台代码与GUI的控件元素属性进行交互,使用功能数据绑定减少了代码量。

    2、组成:WPF中的绑定完成了绑定源和绑定目标的联动一个绑定常常由四部分组成:绑定源、路径、绑定目标及目标属性,同时转换器也是一个非常重要的组成。

    (1)Binding的源

    Binding的源就是数据的源头,数据的源头只要是一个对象,并且通过属性公开自己的数据,即可作为Binding的源。

    Binding的源总结:

    • 把普通CLR类型单个对象指定为Source。包括.NET Framework自带类型的对象和用户自定义类型的对象。
    • 把普通CLR集合类型对象指定为Source。包括数组、List<T>、ObservableCollection<T>等集合类型。
    • 把ADO.NET数据对象指定为Source。包括DataTable和DataView对象。
    • 把依赖对象指定为Source。
    • 把容器DataContext指定为Source。

    1)把控件作为Binding 源与Binding 标记扩展

    <Window x:Class="testBinding2.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <StackPanel>
                <TextBox x:Name="textBox1" Text="{Binding Path=Value,ElementName=slider1}"/>
                <Slider x:Name="slider1" Maximum="100" Minimum="0"/>
            </StackPanel>   
        </Grid>
    </Window>
    

      <TextBox x:Name="textBoxName" BorderBrush="Black" Margin="5" />使用Binding标记扩展语法,等价于C#

    this.textBox.SetBinding(TextBox.TextProperty,new Binding("Value"){ ElementName="slider1"});

    2)使用集合对象作为列表控件的ItemsSource

         WPF中列表式控件派生自ItemsControl类,自然继承了ItemsSource属性,这个属性可以接收一个IEnumerable接口派生类的实例作为自己的值。注意:使用集合类型作为列表控件的ItemsSource时一般考虑使用ObservableCollection<T>代替List<T>,因为ObservableCollection<T>类继承实现了INotifyCollectionChanged和INotifyPropertyChanged接口,能把集合的变化立即通知显示它的列表控件,改变会立即显示出来。

    应用举例:

    前台代码:

    <Window x:Class="testBinding2.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <StackPanel>
                <TextBlock Text="Student ID:"  FontWeight="Bold" Margin="5" />
                <TextBox x:Name="textBoxId" Margin="5"/>
                <TextBlock Text="Student List:" FontWeight="Bold" Margin="5"/>
                <ListBox x:Name="listBoxStudents" Height="180" Margin="5"/>
                    <!--<ListBox.ItemTemplate>
                    </ListBox.ItemTemplate>-->
            </StackPanel>   
        </Grid>
    </Window>
    

    后台代码:

    namespace testBinding2
    {
        /// <summary>
        /// MainWindow.xaml 的交互逻辑
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                List<Student> stuList = new List<Student>()
                {
                    new Student() { Id = 0, Name = "Tim", Age = 29 },
                    new Student() { Id = 1, Name = "Tom", Age = 28 },
                    new Student() { Id = 2, Name = "Kyle", Age = 27 },
                    new Student() { Id = 3, Name = "Tony", Age = 24 },
                    new Student() { Id = 4, Name = "Vina", Age = 23 },
                    new Student() { Id = 5, Name = "Mike", Age = 22 },
                };
                //为ListBox设置Binding
                this.listBoxStudents.ItemsSource = stuList;//数据源
                this.listBoxStudents.DisplayMemberPath = "Name";//路径
                //为TextBox设置Binding
                Binding binding = new Binding("SelectedItem.Id") { Source=this.listBoxStudents};
                this.textBoxId.SetBinding(TextBox.TextProperty,binding);
            }
        }
        //创建一个名为Student的类,它具有Id、Name、Age三个属性
        public class Student
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public int Age { get; set; }
        }
    }
    

     效果:

    2)Binding 的数据流方向(绑定的模式)

    默认情况下,数据既能通过Binding送达目标,也能够从目标返回源。控制Binding数据流向的属性是Mode,它的类型是BindingMode,枚举为 TowWay ,OneWay,OnTime、OneWayToSource和Default。

    OneWay(常规数据流):数据来源是一个数据集合,目标是一个控件元素。

    TowWay:数据来源和目标任意发生改变时都更新数据来源和目标。

     

    (2)Binding 的路径

    Binding 的Path属性指定Binding源的对象哪个属性。如上所示  Slinder控件对象当做源,把它的Value属性作为路径。

    特殊:没有Path的Binding ,即Binding源的本身就是数据。

     

    二、应用

    点击button按钮时TextBox控件的内容改变

    1、界面设计

    <Window x:Class="testBinding.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <StackPanel>
                <TextBox x:Name="textBoxName" BorderBrush="Black" Margin="5" />
                <Button Content="Add Age" Margin="5" Click="Button_Click"/>
            </StackPanel>
        </Grid>
    </Window>

     2、后台设计

    using System.ComponentModel;
    
    namespace testBinding
    {
        /// <summary>
        /// MainWindow.xaml 的交互逻辑
        /// </summary>
        public partial class MainWindow : Window
        {
            Student stu;
            public MainWindow()
            {
                InitializeComponent();
    
                //准备数据源       
                stu = new Student();
                //准备Binding
                Binding binding = new Binding();//创建Binding实例
                binding.Source = stu;//指定数据源
                binding.Path = new PropertyPath("Name");//指定访问路径 
    
                //使用Binding 连接数据源与Bingding目标
                BindingOperations.SetBinding(this.textBoxName,TextBox.TextProperty,binding);//使用binding实例将数据源与目标关联起来
                //参数为 目标;目标的某个属性
    
    
            }
    
            private void Button_Click(object sender, RoutedEventArgs e)
            {
               stu.Name+="Name11";
            }
    
    
        }
    
        class Student:INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
            private string name;
    
            public string Name
            {
                get { return name; }
                set
                {
                    name = value;
                    if(this.PropertyChanged!=null)
                    {
                        this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name"));//当Name的属性值发生改变时,PropertyChanged事件触发
                    }
                }
            }
    
           
        }
    }

     

    展开全文
  • c#--wpf数据绑定binding

    2017-08-09 15:23:54
    xaml  测试binding.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d

    xaml

       

    <Window x:Class="测试binding.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:测试binding"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
        <StackPanel>
            <Button Content="{Binding Path=aa}" ></Button>      //banding  aa    当cd类的name值改变时在view层显示
            <DockPanel Height="100">
                <Button Content="liushaui" Click="btn"></Button>   //写了个click事件来改变数据
            </DockPanel>
        </StackPanel>
    </Window>
    

    MainWindow.xaml.cs


       

    using System;
    using System.Windows;
    
    namespace 测试binding
    {
        /// <summary>
        /// MainWindow.xaml 的交互逻辑
        /// </summary>
        public partial class MainWindow : Window
        {
            private cd cd = new cd();   //将cd binding类 实例化
    
            public MainWindow()
            {
                InitializeComponent();
                this.DataContext = this.cd;   //设置数据源为cd 类的
    
           
            }
    
    
    
            private void btn(object sender, RoutedEventArgs e)
            {
                Random r = new Random();
                  int i=  r.Next();
                cd.name = i.ToString();   //改变cd类的 name  的值
                
            }
        }
    
    
        public class cd: DependencyObject
        {
    
    
            public static DependencyProperty nameProperty;
            public string name
            {
                #region
                get
                {
                    return (string)GetValue(nameProperty);
                }
                set
                {
                    SetValue(nameProperty , value);
                }
                #endregion
            }
    
            public event DependencyPropertyChangedEventHandler OnDependencyPropertyChanged;
            protected static void PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                #region
                cd mn = (cd)d;
    
                if (mn.OnDependencyPropertyChanged != null)
                {
                    mn.OnDependencyPropertyChanged(d, e);
                }
                #endregion
            }
    
    
            static cd()
            {
    
                FrameworkPropertyMetadata metadata = new  FrameworkPropertyMetadata("");   //默认值为空
                metadata.PropertyChangedCallback = new PropertyChangedCallback(PropertyChanged);
                cd.nameProperty = DependencyProperty.Register("aa", typeof(string), typeof(cd), metadata);  //生成 aa binding
    
            }
    
    
            public cd()
            {
                #region
                this.name ="aaaaaa";    // 这个是初始值
                #endregion
            }
    
    
    
        }
    
     
       
    }
    

    展开全文
  • (读完此系列WPF和Silverlight的数据绑定问题你就轻松搞定) 1 Binding to List Data 前面都是绑定到一个对象,下面我们学习绑定到对象列表的方法。 我们还是先组织要绑定的数据,对象所对应的类还是Person,但...

    (读完此系列WPF和Silverlight的数据绑定问题你就轻松搞定

    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数据绑定(Data Binding)错误

    千次阅读 2009-02-13 18:18:00
    WPF的数据绑定功能很强大,允许你在Xaml文件里面直接指定控件要绑定数据的属性,甚至可以绑定到一个函数的返回值...WPF数据绑定内建了跟踪机制。调试程序的时候,如果 数据绑定发生错误的时候,WPF会在Visual Studio
  • wpf 后台绑定数据 binding

    千次阅读 2014-05-26 14:28:50
    http://blog.csdn.net/h82258652/article/details/20577209点击打开链接
  • WPF里分三种BindingBinding, PriorityBinding,MultiBinding,这三种Binding的基类都是BindingBase,而BindingBase又继承于MarkupExtension 1.Binding 中 绑定到其他控件 ElementName   Binding 绑定是 ...
  • WPF数据绑定

    千次阅读 2019-01-23 14:22:17
    WPF中的数据绑定提供了很强大的功能。与普通的WinForm程序相比,其绑定功能为我们提供了很多便利,例如Binding对象的自动通知/刷新,Converter,Validation Rules,Two Way Binding等功能,省去了很多维护的繁琐工作...
  • WPF 数据绑定

    千次阅读 2012-10-19 11:36:07
    WPF中的数据绑定非常的灵活,使用起来也是十分的简单,这里我不扯什么理论知识了发个链接 想仔细研究的同学 可以自己去慢慢看 MSDN http://msdn.microsoft.com/zh-cn/library/ms752347(v=vs.100).aspx 本文主要是...
  • combobox数据绑定List链表集合区分显示值与选择的值 整体效果: 根据combobox选择情况分别打印选取值与显示值 代码: Windows窗体: 1 <Window x:Class="ComboxBinding.MainWindow" 2 xmlns=...
  • 一、自定义类作为源绑定到TextBlock 1.新建一个Student类 public class Student { public Student(string name) { this.Name = name; } public string Name { get; s...
  • WPF databinding example for textbox.
  • WPF 数据绑定 命令绑定 事件绑定 View和ViewModel的通信
  • WPF数据绑定详解

    千次阅读 2010-03-10 17:45:00
    转载自:李小龙的博客http://blog.163.com/bruce_lee04/blog/static/45755321201008102135814/ Windows Presentation Foundation (WPF) 数据绑定为应用程序提供了一种简单而一致的方法来显示数据以及与数据交互。...
  • C# WPF 数据绑定

    2019-09-25 03:12:11
    后台通知: public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) { ...
  • WPF数据绑定模式

    2020-01-08 17:06:41
    三种数据绑定模式 1.OneTime:一次绑定 在绑定创建时使用源数据更新目标,适用于只显示数据而不进行数据的更新。{Binding xxx} xxx表示属性名 默认的绑定模式是一次绑定OneTime。 这种数据绑定模式,只是显示数据而...
  • WPF数据绑定DataGrid

    千次阅读 2014-07-27 23:38:34
    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.SQLite; using System.Data; using System.Data.Common; using System.Windows.Forms;...nam
  • WPF数据绑定 1

    2018-06-22 17:49:19
    1、数据绑定:关联数据源(集合、对象、控件等)和目标(一般是界面的控件)。2、模型:1).目标对象(e g.控件)、2).目标属性(e g.控件属性)、3).数据源对象(e g.类)、4).数据源属性(e g.属性)、5).绑定...
  • WPF 数据绑定 combobox

    2014-05-26 14:50:23
    http://www.cnblogs.com/mantian/archive/2013/01/22/2871775.html 点击打开链接
  • WPF 数据绑定基础

    2013-06-16 14:56:25
    关于WPF数据绑定,本人愚见,将其分为两大类。一类为绑定到界面元素的属性,多用于一些界面设计中,以本人目前的眼界来看,此类需求相对较少;另一类则为用户数据的绑定,多用于数据展示。 下面就几个简单的小例子...
  • WPF数据绑定步骤

    2013-07-20 14:16:53
    为什么要定义一个类型,为了方便尽量不操作控件。MVVM、MVC。 1、定义类,定义属性。 2、new一个类的实例,给要绑定的控件设定DataContext ...Text="{Binding Name}",几乎所有属性都能进行这样的数据绑定
  • WPF数据绑定模型

    2012-04-24 09:59:39
    (1)为指定控件绑定:Content=”{Binding Value,ElementName=sth,Mode=Default}”, ElementName的值表示数据绑定操作的源,Binding后面的项(Value)表示要获取的元素的属性。 为一组控件绑定:DataContext=”{...

空空如也

1 2 3 4 5 ... 20
收藏数 33,480
精华内容 13,392
关键字:

binding