Binding的Source从何而来?

I. Binding to Object

1. Binding data using ObjectDataProvider

AC:Let’s say there is a CLR based data bound object that you are trying to implement. For example a collection of Tool objects, e.g.

  • An Object called Tool that contains a bunch of properties that we want to bind (in this case it just contains a description)
  • A Collection of Tool objects(ToolsCollection); for example to populate a list box etc
  • A Factory to get the reference of ToolsCollection objects which have collection<Tools>
using System;

using System.Collections.Generic;

using System.Collections.ObjectModel;

using System.ComponentModel;

using System.Linq;

using System.Text;

using System.Threading.Tasks;



namespace CLRDataBinding

{

    public class Tool : INotifyPropertyChanged

    {

        private string _description = "";

        public string Description

        {

            get

            {

                return _description;

            }

            set

            {

                if (_description != value)

                {

                    _description = value;

                    NotifyPropertyChanged("Description");

                }

            }

        }

        public Tool(string description)

        {

            _description = description;

        }



        public event PropertyChangedEventHandler PropertyChanged;

        protected void NotifyPropertyChanged(string propName)

        {

            if (PropertyChanged != null)

            {

                PropertyChanged(this, new PropertyChangedEventArgs(propName));

            }

        }



    }

}
View Code
using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Collections.ObjectModel;



namespace CLRDataBinding

{

    public class ToolsCollection : ObservableCollection<Tool>

    {

        public ToolsCollection()

        {

            CreateToolsData();

        }



        private void CreateToolsData()

        {

            for (int loop = 0; loop < 1000; loop++)

            {

                this.Add(new Tool("Tool " + loop.ToString()));

            }

        }

    }

}
View Code
using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;



namespace CLRDataBinding

{

    public class Factory

    {

        public ToolsCollection MyToolsCollection

        {

            get { return new ToolsCollection(); }

        }

    }

}
View Code
<Window x:Class="CLRDataBinding.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:clr="clr-namespace:CLRDataBinding"

        Title="MainWindow"

        Width="525"

        Height="350">

    <Window.Resources>

        <ObjectDataProvider x:Key="FactoryDP" ObjectType="{x:Type clr:Factory}" />

        <DataTemplate x:Key="ToolItemTemplate">

            <StackPanel>

                <TextBlock Text="{Binding Description}" />

            </StackPanel>

        </DataTemplate>

    </Window.Resources>

    <Grid>

        <ListBox ItemTemplate="{StaticResource ToolItemTemplate}" ItemsSource="{Binding Path=MyToolsCollection, Source={StaticResource FactoryDP}}" />

    </Grid>

</Window>
View Code

 

之前一篇文章 对象数据绑定 里提到三个例子,第一个例子用了ObjectDataProvider没有用DataContext,第二个例子用了DataContext没有用 ObjectDataProvider,第三个例子既用了ObjectDataProvider也用了DataContext,但没有提到它们的区别,正 好在Beatriz Costa的blog上看到一篇好文章解释了为什么需要 ObjectDataProvider的问题。

ObjectDataProvider能实现四个特殊功能:

1. 传递参数到构造函数中

使用下面的XAML语句定义一个ObjectDataProvider,它会自动调用MySource类的默认构造函数初始化类
<ObjectDataProvider ObjectType="{x:Type local:MySource}" x:Key="odp1"/>
如果MySource类的构造函数允许传入参数的话,就可以这样定义ObjectDataProvider:
<ObjectDataProvider ObjectType="{x:Type local:MySource}" x:Key="odp1">
  <ObjectDataProvider.ConstructorParameters>
    <system:String>Jupiter</system:String>
  </ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>

2. 绑定到方法

ObjectDataProvider 除了 ObjectType的属性外还有MethodName的属性,MethodName属性将ObjectDataProvider绑定到方法,相当于是对数据源的包装,另外也可以定义方法的传入参数:
<ObjectDataProvider ObjectInstance="{StaticResource odp1}" MethodName="WeightOnPlanet" x:Key="odp2">
  <ObjectDataProvider.MethodParameters>
    <system:Double>95</system:Double>
  </ObjectDataProvider.MethodParameters>
</ObjectDataProvider>

3. 替换数据对象

和使用自己在resource中定义对象不同,ObjectDataProvider可以使里很简单的更换绑定的数据对象,只需要更换一下绑定的数据对象的名字。而使用自己在resource中定义对象,即使定义了相同的x:Key也不能达到自动更新的目的。
另,这里使用DataContext也能达到与ObjectDataProvider同样的效果。

4. 建立异步的数据对象

ObjectDataProvider有IsAsynchronous 可以将数据对象定义为异步的。
默认情况下ObjectDataProvider是同步的,XmlDataProvider是异步。

2. Binding DataContext in Window.DataContext (ObjectDataProvider not needed)

AuctionItem.cs: define Class AuctionItem : INotifyPropertyChanged
MyApp.xaml.cs: define Class AuctionItems : ObservableCollection<AuctionItem>
Window1.xaml.cs: use [CollectionViewSource cv = root.DataContext as CollectionViewSource;] to action in button event handler

Binding Process:

1)Define DataContext in Window1.xaml: 

<Window.DataContext>

    <CollectionViewSource>

      <CollectionViewSource.Source>

        <local:AuctionItems/>



      </CollectionViewSource.Source>

    </CollectionViewSource>

  </Window.DataContext>

2) Binding Listbox:

<ListBox ItemsSource="{Binding Path=.}" IsSynchronizedWithCurrentItem="True">

3) Binding label: (the current item in listbox)

<Label Content="{Binding Path=/}" >

4) DataTemplate

<DataTemplate DataType="{x:Type local:AuctionItem}" >

...

<Image>

       <Image.Source>

                <Binding Path="Image"/>

       </Image.Source>

</Image>

...

More: this sample also shows how to use Converter and MultiBinding

3. Binding DataContext in controls to Global ObjectDataProvider

sample:

MyApp.xaml:

<Application.Resources>

 ...

 <ObjectDataProvider x:Key="Employees" ObjectType="{x:Type local:MSEmployeeCollection}"/>

</Application.Resources>

Window1.xaml:

<StackPanel Margin="10" DataContext="{StaticResource Employees}">

    ...

    <Button Content="{Binding Path=[0]}" />

    <ComboBox ItemsSource="{Binding}" SelectedIndex="0" />

 </StackPanel>

1) DataContext another format : binding to StackPanel
2) Button bind to single item [0]
3) ComblBox bind to multi items, so no Path

II. Binding to XML

1. Use Source include .xml file to XmlDataProvider

<?xml version='1.0' encoding='utf-8'?>

<StackPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Margin="10">

   <StackPanel.Resources>

      <XmlDataProvider x:Key="Blog" Source="http://home.wangjianshuo.com/index.xml"/>

      <DataTemplate x:Key="TitleTemplate">

      <TextBlock Text="{Binding XPath=title}"/>

      </DataTemplate>

      </StackPanel.Resources>

   <Label Content="{Binding Source={StaticResource Blog}, XPath=/rss/channel/title}" FontSize="24" FontWeight="Bold" />

   <Label Content="{Binding Source={StaticResource Blog}, XPath=/rss/channel/description}" FontSize="18" />

   <DockPanel DataContext="{Binding Source={StaticResource Blog}, XPath=/rss/channel/item}" >

 <ListBox DockPanel.Dock="Left" ItemsSource="{Binding}" ItemTemplate="{StaticResource TitleTemplate}" IsSynchronizedWithCurrentItem="True" />

 <TextBox Name="Contents" Text="{Binding XPath=description}" TextWrapping="Wrap" Width="Auto" />

   </DockPanel>

</StackPanel>

2. Use x:XData define the xml structure inside current XmlDataProvider

<StackPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

  <StackPanel.Resources>

    <XmlDataProvider x:Key="FavoriteColors">

 <x:XData>

  <Colors xmlns="">

   <Color>Blue</Color>

   <Color>Black</Color>

   <Color>Green</Color>

   <Color>Red</Color>

  </Colors>

 </x:XData>

    </XmlDataProvider>

  </StackPanel.Resources>

  <TextBlock HorizontalAlignment="Center"

             FontWeight="Bold">

    XML Example

  </TextBlock>

  <ListBox Width="200" Height="300"

           ItemsSource="{Binding Source={StaticResource FavoriteColors},

           XPath=/Colors/Color}">

  </ListBox>

</StackPanel>

III. Binding to Control

1:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">

  <Canvas>

    <TextBox Name="theTextBox" Text="Hello" />

    <TextBlock Canvas.Top="25">

      <TextBlock.Text>

        <Binding ElementName="theTextBox" Path="Text" />

      </TextBlock.Text>

    </TextBlock>

  </Canvas>

</Window>

2:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">

  <Canvas>

    <TextBox Name="theTextBox" Text="Hello" />

    <TextBlock Canvas.Top="25"

               Text="{Binding ElementName=theTextBox, Path=Text}" />

  </Canvas>

</Window>

IX. Binding to ADO.NET

Similar to binding to object, create a dataset and return ds to DataContext.

 

 

 

 

 

你可能感兴趣的:(source)