WPF 数据绑定 定制一个集合的视图 数据提供程序

来源:互联网 发布:php中面向对象的机制 编辑:程序博客网 时间:2024/06/04 19:00

XmlDataProvider

提供了一种简单的方式绑定到一段XML,无论这段XML在内存中的片段或一个完成文件中。

<Page.Resources>    <XmlDataProvider x:Key="xmlData" XPath="Images">        <!-- 数据岛包含在x:XData标记中 -->        <x:XData>            <!-- XML 数据岛 -->            <!-- 用空xmlns标记XML根节点,否则会被默认命名空间影响,XPath查询无法工作 -->            <Images xmlns="">                <Image ID="1">                    <Name>a.jpg</Name>                    <Image ID="3">                        <Name>c.jpg</Name>                    </Image>                </Image>                <Image ID="2">                    <Name>b.jpg</Name>                </Image>            </Images>        </x:XData>    </XmlDataProvider>            <!-- XML文件位于一个独立文件中 -->    <XmlDataProvider x:Key="xmlData2" XPath="Images" Source="Images.xml" />            <!-- 将整个XML数据绑定到一个可以理解层次结构TreeView或Menu的元素上 -->    <!-- 绑定XML的根节点Images样式模板 -->    <!-- 未定义显示x:Key,因为默认以DataType值做了资源键名 -->    <!-- DataType对应XML元素名称 -->    <HierarchicalDataTemplate DataType="Images" ItemsSource="{Binding XPath=*}">        <TextBlock Text="All Images" Background="DeepPink"/>    </HierarchicalDataTemplate>    <!-- 绑定XML的子节点Image样式模板 -->    <HierarchicalDataTemplate DataType="Image" ItemsSource="{Binding XPath=*}">        <TextBlock FontWeight="Bold" Text="{Binding XPath=.}"/>    </HierarchicalDataTemplate>    <!-- 绑定XML元素Image的子节点Name样式模板 -->    <DataTemplate DataType="Name">        <TextBlock Foreground="CornflowerBlue" Text="{Binding XPath=.}"/>    </DataTemplate></Page.Resources>    <StackPanel>    <ListBox ItemsSource="{Binding Source={StaticResource xmlData2}, XPath=Image/Name}"/>            <TreeView ItemsSource="{Binding Source={StaticResource xmlData},XPath=.}"/>    <Menu ItemsSource="{Binding Source={StaticResource xmlData},XPath=.}" /></StackPanel>


ObjectDataProvider

可以提供一个.Net对象为数据源,提供附加能力:

1.声明式的使用带参构造函数实例化对象

<Page x:Class="WPF_Test.Page4"      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"       xmlns:d="http://schemas.microsoft.com/expression/blend/2008"      xmlns:sys="clr-namespace:System;assembly=mscorlib"      xmlns:local="clr-namespace:WPF_Test"      mc:Ignorable="d"       d:DesignHeight="300" d:DesignWidth="300"Title="Page4">        <Page.Resources>        <!-- ObjectDataProvider star -->        <local:PhotoList x:Key="photos"/>        <ObjectDataProvider x:Key="ObjectProvider" ObjectInstance="{StaticResource photos}" />        <ObjectDataProvider x:Key="ObjectProvider_2" ObjectType="{x:Type local:PhotoList}">            <!-- 用带一个参数的构造函数实例化PhotoList对象 -->            <ObjectDataProvider.ConstructorParameters>                <sys:Int32>2</sys:Int32>            </ObjectDataProvider.ConstructorParameters>        </ObjectDataProvider>        <!-- ObjectDataProvider end -->    </Page.Resources>        <StackPanel>        <ListBox SelectedValuePath="ID" DisplayMemberPath="Name" ItemsSource="{Binding Source={StaticResource ObjectProvider_2}}"/>    </StackPanel></Page>
//PhotoList pl = Resources["photos"] as PhotoList;PhotoList pl = ((ObjectDataProvider)Resources["ObjectProvider_2"]).Data as PhotoList;pl.Add(new PhotoModel("lulu", "66" + pl.Value.ToString(), 4, DateTime.Now));

2.绑定到源对象的一个方法

<Page.Resources>    <!-- 绑定一个静态方法 -->    <ObjectDataProvider x:Key="ObjectProvider" ObjectType="{x:Type local:PhotoList}" MethodName="GetValue">        <ObjectDataProvider.MethodParameters>            <sys:String>lulu</sys:String>        </ObjectDataProvider.MethodParameters>    </ObjectDataProvider></Page.Resources>    <StackPanel>    <TextBlock Text="{Binding Source={StaticResource ObjectProvider}}"></TextBlock></StackPanel>
namespace WPF_Test{    //PhotoList继承ObservableCollection可实现自动跟新绑定值    class PhotoList : System.Collections.ObjectModel.ObservableCollection<PhotoModel>    {        public static string GetValue(string value)        {            return value;        }    }}

3.有更多选项做异步数据绑定

 

自定义数据流
Binding支持目标属性直接被用户修改,可以让数据回源。

通过设置Mode属性实现,其值可为:

BindingMode.OneWay:当源改变,目标会跟新

                         TwoWay:源或目标改变,导致另一方面被跟新

                         OneWayToSource:OneWay反向方式,目标改变,源会更新

                          OneTime:同OneWay,但源的改变不会被反映在目标上

注:TextBox.Text无法绑定到集合的Count属性,因为Count属性只读,TextBox.Text默认为TwoWay绑定,需要提供一个可读写属性,需显示修改TextBox绑定模式为OneWay

由于绑定模式的不同,值转换器才有Convert也有ConverBack,当采用TwoWay是,2个方法都有机会调用。
 

当使用了TwoWay或OneWayToSource绑定方式后,可指定何时跟新,如何跟新数据源。

通过Binding的UpdateSourceTrigger属性指定:

UpdateSourceTrigger.PropertyChanged:只要目标属性值改变,源跟新

LostFocus:目标属性值改变后,目标失去焦点,源跟新

Explicit:显示调用BindingExpression.UpdateSource时,源跟新(通过调用Element的GetBindingExpression方法获取)

 

向绑定添加验证规则

跟新数据,会调用验证检查,用规则否决本次跟新后,将数据标记无效。

数据标记无效后,默认会给元素一个新控件模板,显示红色系框。可通过Validation.ErrorTemplate附加属性实现自定义模板。

数据标记无效后,元素Validation.HasError变为true,同时Validation.Error附加事件也会触发(仅当Binding的NotifyOnValidationError设置为true才有效)

<TextBlock Name="txtBlock_1" Text="lulu"></TextBlock><TextBox Name="txt_1">    <TextBox.Text>        <Binding ElementName="txtBlock_1" Path="Text">            <Binding.ValidationRules>                <!-- 自定义验证法则,在文本失去焦点后,数据转换前调用,将不合法数据标记为无效 -->                <local:JpgValidation />            </Binding.ValidationRules>        </Binding>    </TextBox.Text></TextBox>
class JpgValidation:ValidationRule{    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)    {        string fileName = value.ToString();        //检查字符串是否以.jpg结束        if (!fileName.EndsWith(".jpg", StringComparison.InvariantCultureIgnoreCase))        {            return new ValidationResult(false, "不为jpg文件");        }        return new ValidationResult(true, null);    }}


使用不相交源
1.CompositeCollection

提供独立集合或单个集合中的任意项混合。

<Page.Resources>    <local:PhotoList x:Key="photoList"/>    <CompositeCollection x:Key="CompositeCollection">        <!-- 将photoList中的项目作为CompositeCollection的一部分,而非photoList -->        <!-- 因此CompositeCollection中项总数为2+photoList.Count -->        <CollectionContainer Collection="{Binding Source={StaticResource photoList}}"/>        <!-- PhotoModel为含无参构函的类 -->        <local:PhotoModel/>        <local:PhotoModel/>    </CompositeCollection></Page.Resources><ListBox ItemsSource="{Binding Source={StaticResource CompositeCollection}}" />

2.MultiBinding

允许多个绑定汇集,输出给一个单独目标值。

<Page.Resources>    <local:PhotoListConverter x:Key="photoListConverter" />    <local:PhotoModel x:Key="pmodel1"/>    <local:PhotoModel x:Key="pmodel2"/></Page.Resources><TextBox>    <!-- 通过指定转换器,汇合多个绑定值,付给一个元素,设定绑定模式OneWay -->    <MultiBinding Converter="{StaticResource photoListConverter}" Mode="OneWay">        <Binding Source="{StaticResource pmodel1}" Path="Name" />        <Binding Source="{StaticResource pmodel2}" Path="Name" />    </MultiBinding></TextBox>
public class PhotoListConverter : IMultiValueConverter{    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)    {        string total = string.Empty;        foreach (object value in values)        {            total += value.ToString()+",";        }        return total.TrimEnd(',');    }    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)    {        throw new NotImplementedException();    }}

3.PriorityBinding

也封装多个Binding对象,让多个Binding为设置目标而竞争!

如果绑定到一个较慢数据源,在等待时可能需要一个较快的临时数据版本。

<Page.Resources>    <local:SlowSpeed x:Key="HightPri"/>    <local:MediumSpeed x:Key="MediumPri"/>    <local:FastSpeed x:Key="LowPri"/></Page.Resources><TextBlock>    <TextBlock.Text>        <!-- 最后显示结果为SlowSpeed -->        <PriorityBinding>            <!-- 优先级最高,操作耗时最多,应设为异步操作,避免UI阻塞 -->            <Binding Source="{StaticResource HightPri}" Path="Value" IsAsync="True" />            <!-- 操作耗时较多,应设为异步操作,避免UI阻塞 -->            <Binding Source="{StaticResource MediumPri}" Path="Value" IsAsync="True" />            <!-- 优先级最低,操作耗时最少,应设为同步操作 -->            <Binding Source="{StaticResource LowPri}" Path="Value" />        </PriorityBinding>    </TextBlock.Text></TextBlock>
public class SlowSpeed{    private string _value;    public string Value    {        get { return _value; }        set { _value = value; }    }    public SlowSpeed()    {        Thread.Sleep(5000);        _value = "SlowSpeed";    }}public class MediumSpeed{    private string _value;    public string Value    {        get { return _value; }        set { _value = value; }    }    public MediumSpeed()    {        Thread.Sleep(1000);        _value = "MediumSpeed";    }}public class FastSpeed{    private string _value;    public string Value    {        get { return _value; }        set { _value = value; }    }    public FastSpeed()    {        _value = "FastSpeed";    }}
原创粉丝点击