Colabora.NET
 

La nueva WPF GridView

Como personalizarla y añadir múltiples orígenes de datos (primera parte).

 

Fecha: 21/Jun/2007 (20 Junio 2007)
Autor: Juan Pablo Garcia Coello

Mi blog : http://overrider.blogspot.com

 

Nota del Guille:
Este artículo es la versión en español del artículo publicado por el autor en inglés en The Code Project: The new WPF gridview customized 1 of 3

 


Introducción

En este artículo, se pretende explicar como obtener datos de diverso origen y utilizarlos en un gridview y en otros controles .net 3.0. Crear un Gridview para posteriormente personalizarlo y utilizarlo tanto en WPF app y WPF browser app. 

Prerrequisitos

Para poder realizar con éxito el tutorial, necesitarás lo siguiente:

1.    Visual Studio 2005 C#.
2.    Extensiones WPF para VS2005. (o en su defecto utilizar VS Express C# Orcas Beta 1).
3.    Framework .net 3.0.
4.    Microsoft Expression Blend.
5.    SQL Server 2005 Express. (opcional).
6.    MS Access 2003 o sup. (opcional).
7.    Servidor MySQL. (opcional).

Generando la rejilla

Primero debemos crear un nuevo proyecto Visual Studio de tipo C# .net framework 3.0: Window Application (WPF).

Añadimos un ListView que no ListBox, de la seccion "All Controls" de la toolbox) y le cambiamos el nombre a "List1", nos quedará algo similar a:

<Window x:Class="sample1.Window1"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Title="sample1" Height="320" Width="500"
         >
          <Grid>
      <ListView Margin="0,0,0,50" Name="DataList" />
       </Grid>
       </Window>

Si no se agregó automáticamente al código C#, tenemos que crear un control en C# con el mismo nombre que hará referencia al correspondiente XAML, para ello abrimos Window1.g.cs y añadimos el código siguiente : 

internal System.Windows.Controls.ListView DataList;
No hace falta inicializarlo por que ya existe en XAML. Compilamos el programa para ver si va todo correcto.

Fuente de datos XML

Veamos un recordatorio de como se rellenaba el datagridview .net 2.0, posteriormente como realizarlo en XAML estático y despúes con XAML y C# para realizarlo más dinámico.

En los ejemplos de esta sección se utilizará el siguiente código XML de ejemplo en un fichero llamado "data.xml"

<Customers>
       <Customer>
       	<Code>1234</Code>
       	<Name>EPI</Name>
       	<Country>Sesame Street</Country>
       </Customer>
       <Customer>
       	<Code>3234</Code>
       	<Name>Paul</Name>
       	<Country>United Kingdom</Country>
       </Customer>
       <Customer>
       	<Code>3344</Code>
       	<Name>Juan</Name>
       	<Country>Spain</Country>
       </Customer>
       <Customer>
       	<Code>4321</Code>
       	<Name>Dodo</Name>
       	<Country>Mars</Country>
       </Customer>
</Customers>

Recordatorio XML y .net 2.0

Para añadir datos a un datagridview en .net 2.0, lo que tenemos que hacer simplemente es utilizar el código siguiente:

string file = "data.xml";
DataSet ds = new DataSet("Table");
ds.ReadXml(file);
dG1.DataSource = ds.Tables[0].DefaultView;
 

Y con ello obtendremos:



Generando un GridView partiendo de XML usando solo XAML:

Añadimos en el código XAML el siguiente recurso a la ventana <Window> para localizar el origen XML:

<Window.Resources>
<XmlDataProvider x:Key="CustomersDS" Source="C:\data.xml"/>
</Window.Resources>

Ahora modificamos el ListView que tenemos creado para darle aspecto de rejilla:

<ListView Margin="0,0,0,50" ItemTemplate="{DynamicResource CustomerTemplate}" 
ItemsSource
="{Binding Source={StaticResource CustomersDS}, XPath=/Customers/Customer}">
<ListView.View>
<GridView>
<GridViewColumn Header="Code" DisplayMemberBinding="{Binding XPath=Code}"/>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding XPath=Name}"/>
<GridViewColumn Header="Country" DisplayMemberBinding="{Binding XPath=Country}"/>
</GridView>
</ListView.View>
</ListView>

Con esto conseguiremos añadir de forma estática datos XML usando únicamente XAML:


Generando un GridView partiendo de XML usando XAML y C#

Generamos el fichero "data.xml" del apartado anterior. Ahora (me gusta más generarlo así) creamos el origen de datos en la función OnLoad, para ello añadimos el evento Loaded a la ventana en la parte XAML:

<Window x:Class="WindowsApplication7.Window1"
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
...
Loaded
="OnLoad"
>

Y en el código C# de window1.xaml.cs añadimos using System.Data; y el método:

public void OnLoad(Object o, EventArgs e)
{
string file = @"c:\data.xml";
DataSet ds = new DataSet("Table");
ds.ReadXml(file);
List1.DataContext = ds.Tables[0].DefaultView;
}

Ahora falta realizar la correspondencia entre “Table” y el Binding the XAML, quedando el siguiente código:

<Grid x:Name="LayoutRoot">
<ListView Name="List1" Margin="35,34,212,123" ItemTemplate="{DynamicResource CustomerTemplate}"
ItemsSource
="{Binding Path=Table}">
<ListView.View>
<GridView>
<GridViewColumn Header="Code" DisplayMemberBinding="{Binding Path=Code}"/>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Path=Name}"/>
<GridViewColumn Header="Country" DisplayMemberBinding="{Binding Path=Country}"/>
</GridView>
</ListView.View>
</ListView>
</Grid>

Para entender mejor las correspondencias:



Lo bueno de hacerlo de esta forma, es que podemos generar el origen XML en modo de ejecución y modificarlo sobre la marcha.

Fuente de datos SQL Server

Creamos la base de datos “Customers” con la tabla “customers”  de la estructura siguiente:



Y añadimos los datos de ejemplo correspondientes a la tabla:


Recordar crear un usuario que pueda acceder a esa base de datos y activar datareader y datawriter:



Añadimos el namespace  using System.Data.SqlClient; y simplemente modificamos el método OnLoad para tener el siguiente código:

public void OnLoad(Object o, EventArgs e)
{
string s_command = "SELECT Code,Name,Country FROM customers";
SqlConnection connection = new SqlConnection();
SqlDataAdapter adapter = new SqlDataAdapter();
SqlCommand command = new SqlCommand();
command.CommandText = s_command;
adapter.SelectCommand = command;
connection.ConnectionString = "Data Source=192.168.10.9,1433;Initial Catalog=Customers;"
Network Library=DBMSSOCN;User ID=temporalguest;Password='';";"
command.Connection = connection;
DataSet ds = new DataSet();
adapter.Fill(ds,"Table");
List1.DataContext = ds.Tables[0].DefaultView;
connection.Close();
}

NOTA: Aunque las consultas SQL no son CaseSensitive, Las Columnas XAML si lo son, por lo que el campo tiene que coincidir con el nombre del  DisplayMemberBinding.

Fuente de datos Access

Abrimos Access y creamos una nueva base de datos que llamaremos "customers.mdb", al que le agregaremos la tabla “customers”, de forma similar al caso anterior.
Añadimos el namespace  using System.Data.OleDb; y simplemente modificamos el método OnLoad para tener el siguiente código:

public void OnLoad(Object o, EventArgs e)
{

string s_command = "SELECT Code,Name,Country FROM customers";
OleDbConnection connection = new OleDbConnection();
OleDbDataAdapter adapter = new OleDbDataAdapter();
OleDbCommand command = new OleDbCommand();
command.CommandText = s_command;
adapter.SelectCommand = command;
connection.ConnectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data source=C:\customers.mdb";
connection.Open();
command.Connection = connection;
DataSet ds = new DataSet();
adapter.Fill(ds);
List1.DataContext = ds.Tables[0].DefaultView;
connection.Close();

}

Fuente de datos MySql

Primero comentar los requisitos necesarios para hacer funcionar MySql:

  • Descargar e instalar el fichero MySQL.Data, disponible en la dirección aquí:
  • En el proyecto, añadir la referencia MySQL.Data, seleccionando la pestaña Browse::


Teniendo en cuenta que tengamos correctamente instalado MySQL Server, simplemente tenemos que añadir el espacio de nombres  using MySql.Data.MySqlClient; y sustituir la función OnLoad por:

public void OnLoad(Object o, EventArgs e)
{
string s_command = "SELECT Code,Name,Country FROM customers";
MySqlConnection connection = new MySqlConnection();
MySqlCommand command = new MySqlCommand();
MySqlDataAdapter adapter = new MySqlDataAdapter();
command.CommandText = s_command;
adapter.SelectCommand = command;
connection.ConnectionString = "Server=192.168.10.9;Database=Customers;User Id=temporalguest;"
Password=111111;";"
command.Connection = connection;
DataSet ds = new DataSet();
adapter.Fill(ds, "Table");
List1.DataContext = ds.Tables[0].DefaultView;
connection.Close();

}

Personalizando el GridView

Aquí explico como personalizar lo básico de un GridView, en el próximo capítulo se explicarán las nuevas posibilidades respecto al DataGridView.

Personalizando la cabecera

Si queremos personalizar la cabecera de todas las columnas, tenemos que añadir en ListView el estilo:
<GridView ColumnHeaderTemplate="{StaticResource BlueHeader}">

En el caso de que queramos asignar columna por columna el estilo:

<GridViewColumn Header="Code" DisplayMemberBinding="{Binding Path=Code}" 
HeaderTemplate
="{StaticResource BlueHeader}" />

Ahora tenemos que añadir lo que se denomina un recurso en la sección Window:

<Window.Resources>
<DataTemplate x:Key="BlueHeader">
<StackPanel Orientation="Horizontal" Margin="-5,-5,-5,-5" Width="120">
<StackPanel.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF223B84" Offset="1"/>
<GradientStop Color="#FF57A0F4" Offset="0.5"/>
<GradientStop Color="#FF4B94EC" Offset="0.5"/>
</LinearGradientBrush>
</StackPanel.Background>
<TextBlock Margin="10,10,10,10" Text="{Binding}" VerticalAlignment="Center" Foreground="White"/>
</StackPanel>
</DataTemplate>
</Window.Resources>

Obtendremos una vista similar a:

Personalizar el fondo

Este caso es más sencillo, añadimos la propiedad Background al Listview: (lo podemos hacer desde Blend):

<ListView.Background>
<LinearGradientBrush EndPoint="0.939,0.919" StartPoint="0.061,0.081">
<GradientStop Color="#FFFFE07E" Offset="0"/>
<GradientStop Color="#FFFFFAEA" Offset="1"/>
</LinearGradientBrush>
</ListView.Background

Obtendremos:

Personalizar las celdas

Primero vamos a modificar el estilo normal de las celdas, para ello simplemente añadimos al ListView el ItemContainerStyle:

<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}" >
<Setter Property="Height" Value="24" />
<Setter Property="Background" Value="#5EF4E057" />
<Setter Property="Foreground" Value="#FF4B94EC"/>
</Style>
</ListView.ItemContainerStyle>

Ya vemos que va mejorando la rejilla, finalmente veamos un ejemplo de como funcionan los triggers. Uno de lo los eventos posibles sobre un listview, que es “IsMouseOver”, para ello añadimos un Style.Trigger:

<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}" >
<Setter Property="Height" Value="24" />
<Setter Property="Background" Value="#5EF4E057" />
<Setter Property="Foreground" Value="#FF4B94EC"/>

<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Foreground" Value="DarkBlue" />
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFFFC704" Offset="0.986"/>
<GradientStop Color="#FFF4E057" Offset="0.5"/>
<GradientStop Color="#FFF4E057" Offset="0.51"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>

</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>

Finalmente con ello obtenemos una rejilla con un buen estilo, algo realmente dificil de conseguir con .net 2.0:

 

Espacios de nombres usados en el código de este artículo:

System.Data;
System.Data.SqlClient;
System.Data.OleDb;
MySql.Data.MySqlClient;
 




Ir al índice principal de el Guille