Compartilhar via


Capítulo 5: Associação de dados

 

Introdução
Capítulo 1: O modelo de aplicativo "Longhorn"
Capítulo 2: Criando um aplicativo "Longhorn"
Capítulo 3: Controles e XAML
Capítulo 4: Armazenamento

Capítulo 5: Associação de dados

Refatoração Brent
Wise Owl Consulting

Fevereiro de 2004

Sumário

Criando uma associação de dados
Tipos de associação de dados
Transformadores
Fornecendo notificações de alteração de propriedade
Resumo

Associação de dados em seu sentido tradicional significa associar alguns dados subjacentes a um ou mais elementos de interface do usuário. Os dados fornecem as informações a serem exibidas. Os elementos da interface do usuário renderizam as informações no formato apropriado.

"Longhorn" estende a ideia tradicional de associação de dados de várias maneiras. Você pode associar uma propriedade de um elemento de interface do usuário a uma propriedade de qualquer objeto CLR (Common Language Runtime) ou a um atributo de um nó XML.

A associação de dados pode ser unidirecional (em qualquer direção) ou bidirecional. Por exemplo, a associação de dados tradicional tem as informações no fluxo da fonte de dados para seu elemento de interface do usuário associado. Como alternativa, as informações no elemento de interface do usuário podem fluir de volta para a fonte de dados. A associação de dados bidirecional, é claro, dá suporte ao fluxo de informações em cada direção e permite que a entrada do usuário por meio do elemento de interface do usuário atualize os dados na fonte de dados.

A associação de dados também pode ser estática (somente uma vez) ou dinâmica. Com a associação de dados estáticos, a transferência de informações ocorre quando você cria inicialmente a associação de dados. As alterações subsequentes nos valores nos dados não afetam o valor no elemento de interface do usuário. A associação dinâmica de dados permite que as alterações nos dados na fonte de dados se propaguem para o elemento Interface do Usuário e vice-versa.

A associação de dados "Longhorn" também dá suporte à transformação dos dados à medida que eles fluem de e para a fonte de dados e os elementos da interface do usuário. Essa transformação permite que o autor do aplicativo adicione semântica de interface do usuário aos dados.

Algumas transformações típicas podem ser as seguintes:

  • Exibindo números negativos em números vermelhos e positivos em preto
  • Exibindo imagens com base em um contato online ou offline
  • Criando gráficos de barras dinâmicas associando a altura de um retângulo a um preço de ação
  • Animando a posição de uma imagem associando suas coordenadas a uma propriedade de um objeto CLR

A associação de dados "Longhorn" também é fundamentalmente assíncrona. Um elemento de interface do usuário recebe um evento quando uma nova fonte de dados é associada ao elemento . Além disso, à medida que uma fonte de dados coleta seus dados, ela dispara eventos para indicar que seu conteúdo foi alterado.

Pode-se associar dados a qualquer objeto CLR ou XMLnode e, portanto, pode-se facilmente associar dados a vários modelos de dados em "Longhorn"— objetos CLR, XML, conjuntos de dados ADO.NET, mensagens de serviço Web ou objetos WinFS. "Longhorn" também fornece várias classes de fonte de dados internas que permitem que você traga dados de forma assíncrona e de forma fácil e declarativa para um aplicativo. Há fontes de dados específicas para objetos XML, .NET ADO.NET conjuntos de dados e objetos WinFS. O modelo de fonte de dados é extensível, portanto, você pode criar suas próprias classes de fonte de dados personalizadas quando necessário.

Criando uma associação de dados

Você pode associar uma propriedade dinâmica de um elemento de interface do usuário a uma propriedade de qualquer objeto CLR. Para fazer isso, você deve descrever a correspondência desejada entre algum item de uma fonte de dados e o elemento de interface do usuário de destino. Cada correspondência ou associação deve especificar o seguinte:

  • O item da fonte de dados
  • O caminho para o valor apropriado no item de fonte de dados
  • O elemento de interface do usuário de destino
  • A propriedade apropriada do elemento de interface do usuário de destino

A associação de dados

O Framework representa uma associação de dados por uma instância da classe MSAvalon.Data.Bind . Essa classe tem várias propriedades que controlam a associação de dados: Path, BindType, UpdateType, Transformer, Culture, BindFlags e Source.

Defina a propriedade Path como uma cadeia de caracteres que especifica a propriedade ou o valor na fonte de dados à qual o objeto de associação é associado. A propriedade BindType controla a direção e a frequência da associação de dados. Deve ser um dos três valores: OneWay, TwoWay e OneTime. Um tipo de associação OneWay faz com que a associação de dados transfira novos valores da fonte de dados para a propriedade de destino, mas não propaga as alterações na propriedade de destino de volta para a fonte de dados. Um tipo de associação TwoWay propaga as alterações em ambas as direções. Quando você especifica o tipo de associação OneTime , a associação de dados transfere o valor da fonte de dados para a propriedade de destino somente quando você ativa a associação pela primeira vez.

Você pode definir a propriedade Transformer para qualquer objeto que implemente a interface IDataTransformer . Quando a associação de dados propaga um valor, ela passa o valor pelo transformador. O transformador examina o valor de entrada e produz um novo valor como saída. Observe que os valores de entrada e saída não precisam ser do mesmo tipo. Você pode ter um sinalizador inteiro como entrada e produzir arquivos de imagem diferentes como saída.

A propriedade UpdateType determina quando as alterações na propriedade de destino se propagam de volta para a fonte de dados quando o tipo de associação é TwoWay. Você pode especificar um dos três valores: Immediate means propagate the new value to the data source immediately after the target property changes; OnLostFocus significa propagar o valor quando o controle de destino perder o foco de entrada; e Explicit diz para aguardar até que o código chame o objeto de associação e o instrui a propagar o novo valor.

A propriedade Source faz referência ao item de dados de origem da associação. Você pode usar os atributos DataSource, ElementSource, DataContextSource ou ObjectSource para definir a propriedade Source do objeto bind. Use o atributo ElementSource para definir a Origem como um Elemento fornecendo a ID do elemento como o valor do atributo ElementSource . O atributo DataContextSource permite que você defina a Fonte para o contexto de dados de outro elemento definindo a ID do elemento como DataContextSource. Use o atributo ObjectSource para especificar um objeto como a origem da associação. Por fim, o atributo DataSource permite que você defina a Origem como a propriedade Data do DataSource. Isso será discutido em detalhes na seção O Item da Fonte de Dados.

A propriedade Culture permite que você especifique um CultureInfo para associações que precisam ter reconhecimento de cultura.

A propriedade BindFlags dá suporte a um único valor diferente de zero: NotifyOnTransfer. É muito importante entender que uma associação de dados é inerentemente assíncrona. Quando você altera o valor na fonte de dados, a propriedade de destino correspondente não recebe o valor atualizado imediatamente. Pode levar um tempo arbitrário antes que o novo valor se propague para a propriedade de destino. Quando precisar saber quando a associação tiver concluído a atualização da propriedade de destino, defina a propriedade BindFlags como o valor NotifyOnTransfer . Em seguida, a associação de dados disparará o evento MSAvalon.Data.DataTransfer depois de atualizar a propriedade de destino.

Definindo uma expressão de associação usando código

Você pode criar uma associação de dados programaticamente, embora eu espere que você raramente precise ou queira fazer isso. Basta criar uma instância da classe Bind e chamar o método SetBinding. Aqui está um exemplo possível:

using MSAvalon.Data;

Bind binding = new Bind ();
binding.Path = path;
binding.BindType = bindType;
binding.Source = source;
binding.UpdateType = updateType;

element.SetBinding (property, binding);

Como alternativa, aqui está outra maneira de escrever o código anterior usando um dos construtores de conveniência da classe Bind:

using MSAvalon.Data;

Bind binding = new Bind (path, bindType, source, updateType);
element.SetBinding (property, binding);

Você pode usar outros métodos de conveniência, como o método SetBinding em um elemento, e simplificar o código anterior a este:

element.SetBinding (property, path, bindType, source, updateType);

Definindo uma expressão de associação usando marcação

Espero que você prefira definir a maioria das associações de dados usando marcação. Todos os conceitos anteriores ainda se aplicam: você cria um objeto Bind , define suas propriedades com os valores apropriados e o associa a uma propriedade de um elemento de destino. Por exemplo, a marcação a seguir cria um objeto Bind como o valor da propriedade Text do objeto Button.

<DockPanel xmlns="https://schemas.microsoft.com/2003/xaml" />
  <DockPanel.Resources>
     <myNameSpace:Person def:Name="MyPerson" Name="Bob"/>
  </DockPanel.Resources> . . .
  <Button>
    <Button.Content>
      <Bind Path="Name" BindType="OneWay" ObjectSource="{MyPerson}" />
    </Button.Content>
  </Button>

Para associar uma associação de dados a uma propriedade específica do elemento de interface do usuário, use a associação de dados como o valor da propriedade . No exemplo mostrado, a associação de dados associa o recurso chamado MyPerson à propriedade Text do elemento Button porque defini a associação de dados entre as marcas de início e término Button.Text .

A propriedade DockPanel Resources declara que os seguintes elementos filho são recursos. Ao contrário dos elementos XAML regulares, que são instanciados quando o runtime analisa o arquivo XAML, o runtime não cria uma instância de um recurso até que você realmente o use.

No exemplo anterior, a Origem das associações é um objeto Person , portanto, a instância Bind faz referência a essa instância de objeto Person .

O atributo Path especifica o caminho dentro do item de fonte de dados para o valor de interesse. No exemplo anterior, o caminho é simplesmente Name, portanto, a associação recupera a propriedade Name da instância person . No entanto, o caminho pode ser mais complexo. Por exemplo, se a propriedade Name retornasse um objeto com estrutura adicional, o caminho poderia ser algo como Name.FirstName.

O exemplo anterior mostrou como definir uma associação de dados usando uma definição de propriedade complexa para o valor da propriedade Button.Text . No entanto, você pode usar uma definição alternativa e consideravelmente mais compacta para uma expressão de associação de dados. Nesse caso, você define uma cadeia de caracteres como a expressão de associação de dados. A cadeia de caracteres começa com um caractere asterisco, que o compilador XAML interpreta como um caractere de escape e, em seguida, o nome da classe para instanciar e, em seguida, entre parênteses, uma série de pares de valores de nome separados por ponto e vírgula.

<DockPanel >
  §
 <Button Text="*Bind(Path=Name;BindType=OneWay)" />
  §
</DockPanel>

Quando você define uma associação de dados, mas não especifica um valor para a propriedade Source (usando DataSource, ElementSource, DataContextSource ou ObjectSource), a associação de dados recupera a fonte de dados da propriedade DataContext para o elemento atual. Quando o elemento atual não tem DataContext, o objeto de associação recupera o DataContext do elemento pai recursivamente. Isso permite que você defina uma fonte de dados uma vez no elemento apropriado em sua marcação e, em seguida, use essa fonte de dados em várias associações em elementos filho.

No exemplo a seguir, defina a propriedade DataContext do elemento DockPanel como uma associação de dados que faz referência à minha fonte de dados. Efetivamente, todos os elementos filho herdam essa propriedade DataContext quando não a definem como um valor diferente. Como as associações de dados nos elementos Button não especificam um valor para a propriedade Source , a associação usa a origem do DataContext herdado. É claro que você sempre pode especificar uma fonte para fazer com que uma associação de dados específica use uma fonte de dados diferente.

<DockPanel xmlns="http:////schemas.microsoft.com//2003//xaml//"
           DataContext="{MyPerson}>
  §    <Button Text='*Bind(Path="Name";BindType="OneWay")' />
    <Button Text='*Bind(Path="Age";BindType="OneWay")' />
 §</DockPanel>

Tipos de associação de dados

Uma associação de dados específica pode ser de três tipos: OneTime, OneWay e TwoWay. Você define a propriedade BindType como um desses valores enumerados quando declara a associação.

Associação de dados One-Time

Quando você solicita uma associação de dados única, o runtime, usando a fonte de dados e o caminho especificado, recupera o valor de origem e inicializa a propriedade de destino especificada para esse valor. Normalmente, nada acontece posteriormente quando a origem ou a propriedade de destino alteram o valor.

No entanto, há dois casos especiais. Quando o DataContext de um elemento é alterado, efetivamente, a fonte de dados é alterada e, portanto, a associação executa outra transferência única. Além disso, em muitos casos, o contexto de dados refere-se a uma coleção de objetos. Quando o objeto atual de uma coleção é alterado, a associação de dados executa uma transferência única.

Associação de dados One-Way

Quando você solicita a associação de dados unidirecional, o runtime recupera o valor de origem e inicializa a propriedade de destino especificada para esse valor. Sempre que o valor de origem altera a associação de dados recupera o novo valor e reinicializa a propriedade de destino.

Associação de dados Two-Way

Quando você solicita a associação de dados bidirecional, o runtime recupera o valor de origem e inicializa a propriedade de destino especificada para esse valor. Sempre que o valor de origem é alterado, a associação de dados recupera o novo valor e reinicializa a propriedade de destino. Além disso, quando a propriedade de destino altera o valor, por exemplo, quando o usuário digita em um controle de edição, a associação de dados recupera o novo valor da propriedade de destino e o propaga de volta para a origem. Associação de dados bidirecional é o tipo padrão de uma associação de dados.

Transformadores

Um transformador permite converter um valor de um formulário para outro conforme ele se propaga de e para uma fonte de dados para um destino. Você pode usar um transformador para converter um valor de sua representação interna em um valor exibido exclusivo. Por exemplo, você pode usar um transformador para exibir um número de ponto flutuante negativo usando texto vermelho e um número positivo usando texto preto. Você também pode exibir ícones diferentes para várias classificações dignas de crédito para um cliente.

Você também pode usar um transformador como um conversor de tipo de dados. Por exemplo, seu valor de origem pode ser um objeto Point , enquanto a propriedade à qual você deseja associar o valor requer uma instância length .

Um transformador também recebe as informações de cultura para a interface do usuário como um de seus parâmetros. Você pode usar essas informações para adaptar a interface do usuário apresentada à cultura atual do usuário. Por exemplo, você pode fornecer ícones diferentes ao executar em diferentes culturas.

A interface IDataTransformer

Um transformador é qualquer objeto que implementa a interface IDataTransformer . Aqui está a definição da interface:

interface IDataTransformer {
  object Transform (object o, DependencyID id, CultureInfo culture);
  object InverseTransform (object o, PropertyInfo pInfo, CultureInfo culture);
}

Uma associação de dados chama o método Transform ao propagar um valor de origem para uma propriedade de destino. O parâmetro o é o valor de origem, a ID do parâmetro identifica a propriedade de destino e a cultura do parâmetro identifica a cultura da transformação.

A associação de dados chama o método InverseTransform ao propagar um valor de propriedade de destino alterado de volta para a origem. Nesse caso, o parâmetro o é o valor da propriedade de destino alterada e pInfo identifica o tipo para o qual converter o valor. Como antes, a cultura é a cultura da transformação.

Ambos os métodos permitem que você retorne nulo para indicar que a associação não deve propagar um valor na respectiva direção. Aqui está um transformador simples que retorna uma cor com base em um valor inteiro:

<SimpleText Text="*Bind(Path=Name)" Foreground="*Bind(Path=Age; Transformer=AgeToColorTransformer)"/>

public class AgeToColorTransformer: IDataTransformer {
  public object Transform (object o, DependencyID di, CultureInfo culture) {
    int age = (int) o;
    if (age < 0 || age > 120) return Grey;
    if (age <= 30) return Green;
    if (age <= 70) return Gold;
    if (age <= 120) return Red;
  }
  public object InverseTransform (object o, PropertyInfo i, CultureInfo c) {
        return null;
  }
}

Fornecendo notificações de alteração de propriedade

O CLR não fornece uma maneira genérica de um objeto notificar seus clientes de que uma de suas propriedades foi alterada. No entanto, uma associação dinâmica requer essas notificações para que a associação possa propagar valores de propriedade alterados para a propriedade dinâmica de destino. "Longhorn" apresenta a interface IPropertyChange para permitir que um objeto sinalize quando uma de suas propriedades altera o valor. Observe que a interface define um único evento do tipo PropertyChangedEventHandler e que o manipulador de eventos pode recuperar o nome da propriedade alterada usando a propriedade PropertyName do segundo parâmetro para o manipulador.

interface IPropertyChange {
  event PropertyChangedEventHandler PropertyChanged;
}

delegate void PropertyChangedEventHandler (object sender, 
                                           PropertyChangedEventArgs e);

class PropertyChangedEventArgs : EventArgs {
  public virtual string PropertyName { get ;}
}

No código a seguir, reescrevi a classe Person anteriormente no capítulo para dar suporte à alteração das propriedades Nome e Idade e para disparar os eventos apropriados quando essas alterações ocorrerem.

namespace MyNamespace {
  public class Person : IPropertyChange {
    private string m_name;
    private int    m_age;
    public event PropertyChangedEventHandler PropertyChanged;

    public string Name {
      get { return m_name; }
      set {
        if (m_name != value) {
          m_name = value;
          RaisePropertyChangeEvent ("Name");
        }
      }
    }
    public int Age {
      get { return m_age; }
      set {
        if (m_age != value) {
          m_age = value;
          RaisePropertyChangeEvent ("Age");
        }
      }
    }

    private void RaisePropertyChangedEvent (string propertyName) {
      if (PropertyChanged != null)
        PropertyChanged (this, new PropertyChangedEventArgs (propertyName));
    }
    
    public Person (string name, int age) {
      m_name = name; m_age = age;
    }
  }
}

Seu objeto implementa essa interface chamando o delegado PropertyChanged sempre que uma de suas propriedades "interessantes" altera o valor. Observe que você precisa invocar o delegado somente quando uma propriedade usada em uma associação dinâmica alterar o valor. Seu objeto pode ter propriedades para as quais você não dispara notificações de alteração.

Por motivos de desempenho, você deve disparar as notificações de alteração somente quando a propriedade realmente tiver alterado o valor. Quando o objeto não souber qual propriedade alterou o valor, ele poderá solicitar que todas as associações a qualquer propriedade em si sejam atualizadas ou passe String.Empty para o nome da propriedade alterada.

O item de fonte de dados

"Longhorn" fornece um conjunto de fontes de dados internas, que permite que você obtenha dados de forma fácil e declarativa no aplicativo de forma assíncrona e sem bloquear a interface do usuário.

Um item de fonte de dados é qualquer objeto que implementa a interface IDataSource .

interface IDataSource {
        public virtual Object Data { get; }
        public virtual void Refresh()
}

Essa interface tem uma propriedade Data que permite que a associação obtenha os dados do item de fonte de dados. O método Refresh permite que a associação solicite que o item de fonte de dados recupere seus dados quando ele não estiver disponível. "Longhorn" fornece várias classes de fonte de dados e você verá algumas delas em breve.

Em geral, uma implementação de fonte de dados também fornece uma propriedade fortemente tipada que retorna a API nativa do provedor de dados. Por exemplo, as classes SqlDataSource e XmlDataSource fornecem as propriedades DataSet e Document , respectivamente:

class SqlDataSource : IDataSource, … {
   §    DataSet           DataSet { get; }
    §}
class XmlDataSource : IDataSource, … {
    §    XmlDocument       Document { get; }
    §}

Portanto, se você realmente precisar, poderá acessar diretamente o provedor de dados subjacente.

Usando qualquer objeto CLR como uma fonte de dados

A classe ObjectDataSource permite que você crie uma instância de um tipo especificado como um item de fonte de dados. Normalmente, você usará XAML e declarará suas fontes de dados como recursos em sua marcação. Por exemplo, suponha que eu tenha a seguinte definição de uma classe Person em um assembly chamado MyAssembly e que eu gostaria de usar uma instância dessa classe como um item de fonte de dados:

namespace MyNamespace {
  public class Person {
    private string m_name;
    private int m_age;

    public string Name { get { return m_name; } }
    public int Age { get { return m_age; } }

    public Person (string name, int age) {
      m_name = name; m_age = age;
    }
  }
}

A classe Person não precisa de suporte adicional para ser um item de fonte de dados. Posso usar uma instância da classe ObjectDataSource como o item de fonte de dados e informá-la de que o provedor de dados subjacente deve ser uma instância da classe Person . Para fazer isso, posso usar a marcação para declarar uma instância de um ObjectDataSource como um recurso XAML.

<DockPanel>
  <DockPanel.Resources>
    <ObjectDataSource def:Name ="source1"
       TypeName="MyNamespace.Person, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0123456789abcde f"
       Parameters="Brent, 0x30" />
  </DockPanel.Resources>
</DockPanel>

Como sempre, os nomes dos elementos XAML representam nomes de classe framework. Portanto, o elemento ObjectDataSource diz para criar uma instância da classe ObjectDataSource . O valor do atributo def:Name é o nome desse recurso ("source1" no exemplo anterior).

A instância ObjectDataSource criará uma nova instância da classe referenciada por TypeName chamando seu construtor padrão ou, quando você especificar o atributo Parameters , chamando o construtor que melhor corresponde à assinatura do valor do atributo Parameter .

Lembre-se de que a marcação é equivalente ao código, portanto, a marcação anterior é a mesma que o seguinte código:

ObjectDataSource source1 = new ObjectDataSource();
source1.TypeName = "MyNamespace.Person, MyAssembly, Version=1.0.0.0,   
                    Culture=neutral, PublicKeyToken=0123456789abcdef";
source1.Parameters = "Brent, 0x30";

A classe ObjectDataSource também fornece mecanismos para chamar métodos em objetos e se referir a objetos existentes, além de simplesmente instanciar um novo objeto.

Usando uma fonte de dados com associação de dados

É possível declarar uma fonte de dados como um recurso na propriedade Resources de um elemento ou nos recursos no nível do aplicativo. Qualquer fonte de dados declarada nos recursos do aplicativo pode ser usada em todo o aplicativo em qualquer página. Uma fonte de dados definida nos recursos de um elemento só pode ser usada dentro do escopo do elemento.

É possível declarar uma fonte de dados como um recurso na propriedade Resources de um elemento ou nos recursos no nível do aplicativo. Qualquer fonte de dados declarada nos recursos do aplicativo pode ser usada em todo o aplicativo em qualquer página. Uma fonte de dados definida nos recursos de um elemento só pode ser usada dentro do escopo do elemento.

No exemplo mostrado, a associação de dados associa a fonte de dados chamada source1. Você pode definir o atributo DataSource como a ID do recurso de um recurso XAML. Quando o recurso implementa a interface IDataSource , o runtime definirá a propriedade Source da instância Bind como o objeto retornado pela propriedade Data do recurso DataSource especificado. Quando o recurso não implementa a interface IDataSource , o runtime define a propriedade Source da associação para o próprio objeto de recurso.

No exemplo anterior, o atributo DataSource faz referência a um recurso ObjectDataSource . Portanto, a associação solicita a propriedade Data do ObjectDataSource. A fonte de dados, por sua vez, cria uma instância da classe Person conforme especificado na marcação.

No primeiro Botão, a propriedade Source da instância Bind faz referência a essa instância do objeto Person . O caminho é simplesmente Nome, portanto, a associação recupera a propriedade Name da instância person .

No segundo Botão, DataContext está associado ao ObjectDataSource. Essa ação definirá DataContext do botão para o objeto Person para que todas as associações em Button usem o objeto Person como a fonte padrão para suas associações.

Também é possível associar dados a qualquer uma das fontes de dados disponíveis. Algumas das outras fontes de dados enviadas com "Longhorn" são mencionadas nos parágrafos a seguir. Outros, como fontes de dados para obter dados de serviços Web, estarão online.

Usando XML como uma fonte de dados

A classe XmlDataSource é uma fonte de dados que usa um DOM (Modelo de Objeto de Documento) XML como o provedor de dados subjacente. Você pode usar a marcação para criar o DOM a partir de uma URL (Uniform Resource Locator) referenciando um fluxo XML. Você também pode criar o DOM fornecendo o XML embutido com a marcação, como demonstra o exemplo a seguir:

Usando o URI

<DockPanel>
  <DockPanel.Resources>
    <XmlDataSource def:Name="source2"
       Source="http://www.wiseowl.com/People.xml"
       XPath="/People/Person[@Age>21]" />

Usando marcação embutida

    <XmlDataSource def:Nsme="source3"
       XPath="/People/Person[@Age>50]" >
       <People>
           <Person Name='Bambi' Age='61'>
           <Person Name='Bozo' Age='54'>
           <Person Name='Brent' Age='48'>
           §       </People>
    </XmlDataSource>
</DockPanel.Resources> 
</DockPanel>

Usando um Conjunto de Dados como uma Fonte de Dados

A classe SqlDataSource é uma fonte de dados que usa um DataSet como o provedor de dados subjacente. Ele cria um DataSet e o preenche executando um comando SQL no banco de dados.

<DockPanel>
  <DockPanel.Resources>
    <SqlDataSource def:Name="source4">
      ConnectionString="server=localhost;Database=UserGroup"
       SelectCommand="SELECT * FROM Members" />
    </SqlDataSource>
  <DockPanel.Resources> 
</DockPanel>

Como alternativa, você pode usar a classe ObjectDataSource e associar a uma classe derivada de DataSet fortemente tipada que você definiu em um arquivo code-behind.

<DockPanel>
  <DockPanel.Resources >
  <ObjectDataSource def:Name="sds1"
    Type="MyDataset"/>
  </ObjectDataSource>
 </DockPanel.Resources>
</DockPanel>

Usando o Armazenamento do Windows como fonte de dados

A classe WinFS DataSource usa o WinFS como o provedor de dados subjacente. Você pode usá-lo para associar às informações diárias mantidas pelo Armazenamento do Microsoft® Windows®.

<DockPanel>
  <DockPanel.Resources>
    <WinFSDataSource ContextString="c:\">
      <WinFSDataSource.Query 
    Type="Person" Filter="DisplayName='Ted'" Sort="DisplayName ASC">
        <Query.ProjectionOptions Field="DisplayName" />
        <Query.ProjectionOptions Field="Birthdate">
          <Projection.ProjectionOptions … />
        </Query.ProjectionOptions>
      </ WinFSDataSource.Query>
    </WinFSDataSource>
  </DockPanel.Resources>
</DockPanel>

Usando uma fonte de dados personalizada

Você também pode especificar uma classe personalizada como uma fonte de dados. A classe deve implementar a interface IDataSource . Normalmente, você desejará associar um prefixo de namespace XML ao namespace da classe personalizada e, em seguida, usar o nome de classe qualificado por prefixo na marcação como de costume:

<Canvas … >
  §   
  <Canvas.Resources>
    <WO:InfraredDataSource def:Name="source8"
       PropA='value1'
       PropB='value2'
    </WO:InfraredDataSource>
  </Canvas.Resources>
</Canvas>

Resumo

A associação de dados fornece um método fácil e eficiente para conectar informações a um elemento de interface do usuário que exibe os dados. Você obtém a propagação automática dos valores em qualquer direção, uma vez ou repetidamente, com a capacidade de converter a representação de dados em tempo real quando necessário. E você pode fazer isso com pouca ou nenhuma codificação programática usando marcação. A associação de dados permite que você obtenha os dados onde deseja e passe a gravar o restante do aplicativo.

Prossiga para o Capítulo 6: Comunicação