Cenni preliminari sui modelli di dati

 

Data di pubblicazione: giugno 2016

Il Entity with relative path '../Token/TLA2%23tla_winclient_md.md' can not be found, for source topic '{"project_id":"3fedad16-eaf1-41a6-8f96-0c1949c68f32","entity_id":"0f4d9f8c-0230-4013-bd7b-e8e7fed01b4a","entity_type":"Article","locale":"it-IT"}'. modello ai modelli di dati offre una notevole flessibilità per definire la presentazione dei dati. Entity with relative path '../Token/TLA2%23tla_winclient_md.md' can not be found, for source topic '{"project_id":"3fedad16-eaf1-41a6-8f96-0c1949c68f32","entity_id":"0f4d9f8c-0230-4013-bd7b-e8e7fed01b4a","entity_type":"Article","locale":"it-IT"}'.controlli dispongono di funzionalità incorporate per supportare la personalizzazione della presentazione dei dati. In questo argomento viene illustrato innanzitutto come definire un DataTemplate e vengono presentate altre funzionalità di modello di dati, ad esempio la selezione di modelli in base a logica personalizzata e il supporto per la visualizzazione di dati gerarchici.

Entity with relative path '../Token/autoOutline_md.md' can not be found, for source topic '{"project_id":"3fedad16-eaf1-41a6-8f96-0c1949c68f32","entity_id":"0f4d9f8c-0230-4013-bd7b-e8e7fed01b4a","entity_type":"Article","locale":"it-IT"}'.

In questo argomento è incentrato sulle funzionalità dei modelli dati e non viene fornita un'introduzione dei concetti di associazione dati. Per informazioni sui concetti relativi all'associazione dati di base, vedere il Cenni preliminari sull'associazione dati.

DataTemplate riguarda la presentazione dei dati ed è una delle numerose funzionalità fornite da di Entity with relative path '../Token/TLA2%23tla_winclient_md.md' can not be found, for source topic '{"project_id":"3fedad16-eaf1-41a6-8f96-0c1949c68f32","entity_id":"0f4d9f8c-0230-4013-bd7b-e8e7fed01b4a","entity_type":"Article","locale":"it-IT"}'. modello di stili e modelli. Per un'introduzione di Entity with relative path '../Token/TLA2%23tla_winclient_md.md' can not be found, for source topic '{"project_id":"3fedad16-eaf1-41a6-8f96-0c1949c68f32","entity_id":"0f4d9f8c-0230-4013-bd7b-e8e7fed01b4a","entity_type":"Article","locale":"it-IT"}'. modello di stili e modelli, ad esempio come utilizzare un stile per impostare le proprietà sui controlli, vedere il di stili e modelli argomento.

Inoltre, è importante comprendere Resources, che sono essenzialmente ciò che consentono ad esempio oggetti stile e DataTemplate per essere riutilizzati. Per ulteriori informazioni sulle risorse, vedere risorse XAML.

Entity with relative path '../Token/autoOutline_md.md' can not be found, for source topic '{"project_id":"3fedad16-eaf1-41a6-8f96-0c1949c68f32","entity_id":"0f4d9f8c-0230-4013-bd7b-e8e7fed01b4a","entity_type":"Article","locale":"it-IT"}'.

Per illustrare il motivo DataTemplate è importante, passiamo a esaminare un esempio di associazione dati. In questo esempio, abbiamo un ListBox associato a un elenco di Task oggetti. Ogni Task oggetto ha un TaskName (stringa), un Description (stringa), un Priority (int) e una proprietà di tipo TaskType, ovvero un Enum con valori Home e Work.

<Window x:Class="SDKSample.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="clr-namespace:SDKSample"
  Title="Introduction to Data Templating Sample">
  <Window.Resources>
    <local:Tasks x:Key="myTodoList"/>


</Window.Resources>
  <StackPanel>
    <TextBlock Name="blah" FontSize="20" Text="My Task List:"/>
    <ListBox Width="400" Margin="10"
             ItemsSource="{Binding Source={StaticResource myTodoList}}"/>

  </StackPanel>
</Window>

Senza un DataTemplate

Senza un DataTemplate, il nostro ListBox attualmente è simile al seguente:

Esempio schermata to Data templating

Qual è il problema è che senza istruzioni specifiche, il ListBox per impostazione predefinita chiama ToString quando si tenta di visualizzare gli oggetti nella raccolta. Pertanto, se il Task esegue l'override dell'oggetto di ToString (metodo), il ListBox consente di visualizzare la rappresentazione di stringa di ogni oggetto di origine nella raccolta sottostante.

Ad esempio, se il Task classe esegue l'override di ToString metodo in questo modo, in cui name è il campo per il TaskName proprietà:

      public override string ToString()
      {
          return name.ToString();
      }

Il ListBox simile al seguente:

Esempio schermata to Data templating

Tuttavia, che è limitante e poco flessibile. Inoltre, se si desidera associare a XML dati, non sarà possibile eseguire l'override ToString.

Definizione di DataTemplate semplice

La soluzione consiste nel definire un DataTemplate. Un modo per farlo consiste nell'impostare il ItemTemplate proprietà del ListBox per un DataTemplate. Specificare nel DataTemplate diventa la struttura visiva dell'oggetto dati. Nell'esempio DataTemplate è piuttosto semplice. Vengono fornite istruzioni che ogni elemento viene visualizzato come tre TextBlock elementi all'interno di un StackPanel. Ogni TextBlock elemento è associato a una proprietà del Task (classe).

    <ListBox Width="400" Margin="10"
             ItemsSource="{Binding Source={StaticResource myTodoList}}">
       <ListBox.ItemTemplate>
         <DataTemplate>
           <StackPanel>
             <TextBlock Text="{Binding Path=TaskName}" />
             <TextBlock Text="{Binding Path=Description}"/>
             <TextBlock Text="{Binding Path=Priority}"/>
           </StackPanel>
         </DataTemplate>
       </ListBox.ItemTemplate>
     </ListBox>

I dati sottostanti per gli esempi in questo argomento sono una raccolta di CLR oggetti. Se si esegue l'associazione XML dati, i concetti fondamentali sono uguali, ma esiste una leggera differenza sintattica. Ad esempio, anziché Path=TaskName, è necessario impostare XPath a @TaskName (se TaskName è un attributo del XML nodo).

Ora il nostro ListBox simile al seguente:

Esempio schermata to Data templating

Creazione di DataTemplate come una risorsa

Nell'esempio precedente è stato definito il DataTemplate inline. È più comune definire nella sezione delle risorse può essere un oggetto riutilizzabile, come nell'esempio seguente:

  <Window.Resources>

    <DataTemplate x:Key="myTaskTemplate">
      <StackPanel>
        <TextBlock Text="{Binding Path=TaskName}" />
        <TextBlock Text="{Binding Path=Description}"/>
        <TextBlock Text="{Binding Path=Priority}"/>
      </StackPanel>
    </DataTemplate>

</Window.Resources>

Ora è possibile utilizzare myTaskTemplate come una risorsa, come nell'esempio seguente:

    <ListBox Width="400" Margin="10"
             ItemsSource="{Binding Source={StaticResource myTodoList}}"
             ItemTemplate="{StaticResource myTaskTemplate}"/>

Poiché myTaskTemplate è una risorsa, è possibile utilizzarlo in altri controlli che dispongono di una proprietà che accetta un DataTemplate tipo. Come illustrato in precedenza, per ItemsControl oggetti, ad esempio il ListBox, è il ItemTemplate proprietà. Per ContentControl oggetti, è il ContentTemplate proprietà.

La proprietà DataType

Il DataTemplate classe dispone di un DataType proprietà che è molto simile al TargetType proprietà del stile (classe). Pertanto, anziché specificare un x:Key per il DataTemplate nell'esempio precedente, è possibile eseguire le operazioni seguenti:

    <DataTemplate DataType="{x:Type local:Task}">
      <StackPanel>
        <TextBlock Text="{Binding Path=TaskName}" />
        <TextBlock Text="{Binding Path=Description}"/>
        <TextBlock Text="{Binding Path=Priority}"/>
      </StackPanel>
    </DataTemplate>

Questo DataTemplate viene applicata automaticamente a tutti Task oggetti. Si noti che in questo caso il x:Key è impostato in modo implicito. Pertanto, se si assegna a questo DataTemplate un x:Key valore, si esegue l'override implicita x:Key e DataTemplate non viene applicato automaticamente.

Se si associa un ContentControl a una raccolta di Task oggetti, il ContentControl non utilizza il comando precedente DataTemplate automaticamente. Infatti, l'associazione in un ContentControl richiede ulteriori informazioni per distinguere se si desidera associare a un intero insieme o i singoli oggetti. Se il ContentControl sta rilevando la selezione di un ItemsControl tipo, è possibile impostare il percorso proprietà del ContentControl associazione a "/" per indicare che si è interessati all'elemento corrente. Per un esempio, vedere associare a una raccolta e visualizzare informazioni in base alla selezione. In caso contrario, è necessario specificare il DataTemplate in modo esplicito, impostando il ContentTemplate proprietà.

Il DataType proprietà è particolarmente utile quando si dispone di un CompositeCollection di diversi tipi di oggetti dati. Per un esempio, vedere implementare un oggetto CompositeCollection.

Attualmente i dati vengono visualizzati con le informazioni necessarie, ma esiste senz'altro margine di miglioramento. Di seguito verrà migliorata la presentazione aggiungendo un bordo, grigliae alcuni TextBlock elementi che descrivono i dati da visualizzare.


    <DataTemplate x:Key="myTaskTemplate">
      <Border Name="border" BorderBrush="Aqua" BorderThickness="1"
              Padding="5" Margin="5">
        <Grid>
          <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
          </Grid.RowDefinitions>
          <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
          </Grid.ColumnDefinitions>
          <TextBlock Grid.Row="0" Grid.Column="0" Text="Task Name:"/>
          <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=TaskName}" />
          <TextBlock Grid.Row="1" Grid.Column="0" Text="Description:"/>
          <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=Description}"/>
          <TextBlock Grid.Row="2" Grid.Column="0" Text="Priority:"/>
          <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path=Priority}"/>
        </Grid>
      </Border>

    </DataTemplate>

La schermata seguente mostra il ListBox con questa modifica DataTemplate:

Esempio schermata to Data templating

È possibile impostare HorizontalContentAlignment a Stretch sul ListBox per assicurarsi che la larghezza degli elementi occupi l'intero spazio:

    <ListBox Width="400" Margin="10"
         ItemsSource="{Binding Source={StaticResource myTodoList}}"
         ItemTemplate="{StaticResource myTaskTemplate}" 
         HorizontalContentAlignment="Stretch"/>

Con il HorizontalContentAlignment impostata su Stretch, ListBox ora simile al seguente:

Esempio schermata to Data templating

Utilizzo di DataTrigger per applicare valori di proprietà

La presentazione corrente viene indicato se un Task è un'attività principale o un'attività di office. Tenere presente che il Task oggetto ha un TaskType proprietà di tipo TaskType, che costituisce un'enumerazione con i valori Home e Work.

Nell'esempio seguente, il DataTrigger imposta il BorderBrush dell'elemento denominato border a Yellow se il TaskType è TaskType.Home.

    <DataTemplate x:Key="myTaskTemplate">

    <DataTemplate.Triggers>
      <DataTrigger Binding="{Binding Path=TaskType}">
        <DataTrigger.Value>
          <local:TaskType>Home</local:TaskType>
        </DataTrigger.Value>
        <Setter TargetName="border" Property="BorderBrush" Value="Yellow"/>
      </DataTrigger>
    </DataTemplate.Triggers>

    </DataTemplate>

L'applicazione ora è simile al seguente. Principali attività visualizzati con un bordo giallo e le attività di office con un bordo azzurro:

Esempio schermata to Data templating

In questo esempio il DataTrigger utilizza un Setter per impostare un valore della proprietà. Le classi trigger dispongono inoltre di EnterActions e ExitActions le proprietà che consentono di avviare un set di azioni, ad esempio animazioni. Inoltre, è inoltre disponibile un MultiDataTrigger classe che consente di applicare le modifiche basate su più valori di proprietà con associazione a dati.

Un modo alternativo per ottenere lo stesso risultato consiste nell'associare il BorderBrush proprietà per il TaskType proprietà e utilizzare un convertitore di valori per restituire il colore in base il TaskType valore. Creazione dell'effetto precedente utilizzando un convertitore è leggermente più efficiente in termini di prestazioni. Inoltre, la creazione di un convertitore personalizzato offre maggiore flessibilità poiché di fornire la logica personalizzata. In definitiva, la scelta dipende dallo scenario e le preferenze. Per informazioni su come scrivere un convertitore, vedere IValueConverter.

Cosa appartiene un DataTemplate?

Nell'esempio precedente, è stato inserito il trigger all'interno di DataTemplate utilizzando il DataTemplate. I trigger proprietà. Il Setter del trigger imposta il valore di una proprietà di un elemento (il bordo elemento) che si trova all'interno di DataTemplate. Tuttavia, se le proprietà che il Setters si occupano della non sono proprietà degli elementi che sono all'interno dell'oggetto DataTemplate, può essere più appropriato impostare le proprietà utilizzando un stile per il ListBoxItem classe (se il controllo si associa un ListBox). Ad esempio, se si desidera che il Trigger per animare il opacità valore dell'elemento quando si posiziona il mouse su un elemento, si definiscono trigger all'interno di un ListBoxItem stile. Per un esempio, vedere il Introduzione agli stili e modelli.

In generale, tenere presente che il DataTemplate viene applicata a ogni oggetto generato ListBoxItem (per ulteriori informazioni su come e dove viene effettivamente applicato, vedere il ItemTemplate pagina.). Il DataTemplate riguarda esclusivamente la presentazione e l'aspetto degli oggetti dati. Nella maggior parte dei casi, tutti gli altri aspetti della presentazione, ad esempio che cos'è un elemento simile a quando è selezionata o il ListBox definisce gli elementi, non fanno parte della definizione di un DataTemplate. Per un esempio, vedere il stili e modelli di ItemsControl sezione.

In la proprietà DataType sezione discussa che è possibile definire modelli di dati diversi per gli oggetti dati diversi. Che risulta particolarmente utile quando si dispone di un CompositeCollection di diversi tipi o insiemi con elementi di tipi diversi. Nel utilizzare DataTrigger per applicare valori di proprietà sezione, è stato illustrato che se si dispone di una raccolta dello stesso tipo di oggetti dati è possibile creare un DataTemplate e quindi utilizzare i trigger per applicare le modifiche in base ai valori di proprietà di ogni oggetto dati. Tuttavia, i trigger consentono di applicare i valori delle proprietà o avviare le animazioni ma non offrono la flessibilità necessaria per ricostruire la struttura degli oggetti dati. Alcuni scenari potrebbero essere necessario creare un altro DataTemplate per dati gli oggetti dello stesso tipo, ma proprietà diverse.

Ad esempio, quando un Task oggetto ha un Priority valore 1, si consiglia di fornire un aspetto completamente diverso per fungere da un avviso. In tal caso, si crea un DataTemplate per la visualizzazione di priorità elevata Task oggetti. Aggiungere il seguente DataTemplate alla sezione risorse:

    <DataTemplate x:Key="importantTaskTemplate">
      <DataTemplate.Resources>
        <Style TargetType="TextBlock">
          <Setter Property="FontSize" Value="20"/>
        </Style>
      </DataTemplate.Resources>
      <Border Name="border" BorderBrush="Red" BorderThickness="1"
              Padding="5" Margin="5">
        <DockPanel HorizontalAlignment="Center">
          <TextBlock Text="{Binding Path=Description}" />
          <TextBlock>!</TextBlock>
        </DockPanel>
      </Border>
    </DataTemplate>

Si noti nell'esempio viene utilizzata la DataTemplate. Risorse proprietà. Risorse definite in questa sezione sono condivise dagli elementi all'interno di DataTemplate.

Per fornire la logica per scegliere quale DataTemplate da utilizzare dipende il Priority valore dell'oggetto dati, creare una sottoclasse di DataTemplateSelector ed eseguire l'override di SelectTemplate (metodo). Nell'esempio seguente, il SelectTemplate metodo fornisce la logica per restituire il modello appropriato in base al valore della Priority proprietà. Il modello da restituire viene trovato nelle risorse di busta finestra elemento.

using System.Windows;
using System.Windows.Controls;

namespace SDKSample
{
    public class TaskListDataTemplateSelector : DataTemplateSelector
    {
        public override DataTemplate
            SelectTemplate(object item, DependencyObject container)
        {
            FrameworkElement element = container as FrameworkElement;

            if (element != null && item != null && item is Task)
            {
                Task taskitem = item as Task;

                if (taskitem.Priority == 1)
                    return
                        element.FindResource("importantTaskTemplate") as DataTemplate;
                else
                    return
                        element.FindResource("myTaskTemplate") as DataTemplate;
            }

            return null;
        }
    }
}

È quindi possibile dichiarare il TaskListDataTemplateSelector come risorsa:

  <Window.Resources>

    <local:TaskListDataTemplateSelector x:Key="myDataTemplateSelector"/>

</Window.Resources>

Per utilizzare la risorsa selettore di modello, assegnare il ItemTemplateSelector proprietà del ListBox. Il ListBox chiamate di SelectTemplate metodo il TaskListDataTemplateSelector per ognuno degli elementi nella raccolta sottostante. La chiamata passa l'oggetto dati come parametro dell'elemento. Il DataTemplate restituito dal metodo viene quindi applicato all'oggetto dati.

    <ListBox Width="400" Margin="10"
             ItemsSource="{Binding Source={StaticResource myTodoList}}"
             ItemTemplateSelector="{StaticResource myDataTemplateSelector}"
             HorizontalContentAlignment="Stretch"/>

Il selettore di modello sul posto, il ListBox viene visualizzato come segue:

Esempio schermata to Data templating

Questa operazione conclude la discussione di questo esempio. Per l'esempio completo, vedere Introduction to Data Templating Sample.

Anche se il ItemsControl non è l'unico tipo di controllo che è possibile utilizzare un DataTemplate , è uno scenario molto comune per associare un ItemsControl a una raccolta. Nel cosa appartiene un DataTemplate sezione è stato illustrato che la definizione di DataTemplate solo devono essere prese in considerazione la presentazione dei dati. Per sapere quando non è consigliabile utilizzare un DataTemplate è importante comprendere le diverse proprietà di stile e modello fornite dal ItemsControl. Nell'esempio seguente è progettato per illustrare la funzione di ciascuna di queste proprietà. Il ItemsControl in questo esempio è associato allo stesso Tasks insieme come nell'esempio precedente. A scopo dimostrativo, gli stili e modelli in questo esempio sono tutti dichiarati inline.

    <ItemsControl Margin="10"
                  ItemsSource="{Binding Source={StaticResource myTodoList}}">
      <!--The ItemsControl has no default visual appearance.
          Use the Template property to specify a ControlTemplate to define
          the appearance of an ItemsControl. The ItemsPresenter uses the specified
          ItemsPanelTemplate (see below) to layout the items. If an
          ItemsPanelTemplate is not specified, the default is used. (For ItemsControl,
          the default is an ItemsPanelTemplate that specifies a StackPanel.-->
      <ItemsControl.Template>
        <ControlTemplate TargetType="ItemsControl">
          <Border BorderBrush="Aqua" BorderThickness="1" CornerRadius="15">
            <ItemsPresenter/>
          </Border>
        </ControlTemplate>
      </ItemsControl.Template>
      <!--Use the ItemsPanel property to specify an ItemsPanelTemplate
          that defines the panel that is used to hold the generated items.
          In other words, use this property if you want to affect
          how the items are laid out.-->
      <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
          <WrapPanel />
        </ItemsPanelTemplate>
      </ItemsControl.ItemsPanel>
      <!--Use the ItemTemplate to set a DataTemplate to define
          the visualization of the data objects. This DataTemplate
          specifies that each data object appears with the Proriity
          and TaskName on top of a silver ellipse.-->
      <ItemsControl.ItemTemplate>
        <DataTemplate>
          <DataTemplate.Resources>
            <Style TargetType="TextBlock">
              <Setter Property="FontSize" Value="18"/>
              <Setter Property="HorizontalAlignment" Value="Center"/>
            </Style>
          </DataTemplate.Resources>
          <Grid>
            <Ellipse Fill="Silver"/>
            <StackPanel>
              <TextBlock Margin="3,3,3,0"
                         Text="{Binding Path=Priority}"/>
              <TextBlock Margin="3,0,3,7"
                         Text="{Binding Path=TaskName}"/>
            </StackPanel>
          </Grid>
        </DataTemplate>
      </ItemsControl.ItemTemplate>
      <!--Use the ItemContainerStyle property to specify the appearance
          of the element that contains the data. This ItemContainerStyle
          gives each item container a margin and a width. There is also
          a trigger that sets a tooltip that shows the description of
          the data object when the mouse hovers over the item container.-->
      <ItemsControl.ItemContainerStyle>
        <Style>
          <Setter Property="Control.Width" Value="100"/>
          <Setter Property="Control.Margin" Value="5"/>
          <Style.Triggers>
            <Trigger Property="Control.IsMouseOver" Value="True">
              <Setter Property="Control.ToolTip"
                      Value="{Binding RelativeSource={x:Static RelativeSource.Self},
                              Path=Content.Description}"/>
            </Trigger>
          </Style.Triggers>
        </Style>
      </ItemsControl.ItemContainerStyle>
    </ItemsControl>

Di seguito è riportata una schermata dell'esempio quando viene sottoposto a rendering:

Schermata di esempio ItemsControl

Si noti che invece di utilizzare il ItemTemplate, è possibile utilizzare il ItemTemplateSelector. Vedere la sezione precedente per un esempio. Analogamente, anziché utilizzare il ItemContainerStyle, è possibile utilizzare il ItemContainerStyleSelector.

Due altre proprietà correlate allo stile di ItemsControl che non sono illustrate di seguito sono GroupStyle e GroupStyleSelector.

Finora sono state analizzate unicamente associare e visualizzare una singola raccolta. A volte è necessario una raccolta che contiene altre raccolte. Il HierarchicalDataTemplate classe è progettata per essere utilizzato con HeaderedItemsControl tipi per visualizzare tali dati. Nell'esempio seguente, ListLeagueList è un elenco di League oggetti. Ogni League oggetto ha un Name e una raccolta di Division oggetti. Ogni Division ha un Name e una raccolta di Team oggetti e ogni Team oggetto ha un Name.

<Window x:Class="SDKSample.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="HierarchicalDataTemplate Sample"
  xmlns:src="clr-namespace:SDKSample">
  <DockPanel>
    <DockPanel.Resources>
      <src:ListLeagueList x:Key="MyList"/>

      <HierarchicalDataTemplate DataType    = "{x:Type src:League}"
                                ItemsSource = "{Binding Path=Divisions}">
        <TextBlock Text="{Binding Path=Name}"/>
      </HierarchicalDataTemplate>

      <HierarchicalDataTemplate DataType    = "{x:Type src:Division}"
                                ItemsSource = "{Binding Path=Teams}">
        <TextBlock Text="{Binding Path=Name}"/>
      </HierarchicalDataTemplate>

      <DataTemplate DataType="{x:Type src:Team}">
        <TextBlock Text="{Binding Path=Name}"/>
      </DataTemplate>
    </DockPanel.Resources>

    <Menu Name="menu1" DockPanel.Dock="Top" Margin="10,10,10,10">
        <MenuItem Header="My Soccer Leagues"
                  ItemsSource="{Binding Source={StaticResource MyList}}" />
    </Menu>

    <TreeView>
      <TreeViewItem ItemsSource="{Binding Source={StaticResource MyList}}" Header="My Soccer Leagues" />
    </TreeView>

  </DockPanel>
</Window>

Nell'esempio viene illustrato che con l'utilizzo di HierarchicalDataTemplate, è possibile visualizzare facilmente i dati dell'elenco che contiene altri elenchi. Di seguito è riportata una schermata dell'esempio.

Schermata di esempio HierarchicalDataTemplate

Associazione dati
Trovare elementi generati da un DataTemplate
Stili e modelli
Cenni preliminari sull'associazione dati
Cenni preliminari sui modelli e stili di intestazione di colonna GridView

Mostra: