<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>LINQ</title>
        <link>http://blogs.ugidotnet.org/pietrolibroblog/category/LINQ.aspx</link>
        <description>LINQ</description>
        <language>it-IT</language>
        <copyright>Pietro Libro</copyright>
        <managingEditor>pietro.libro@libero.it</managingEditor>
        <generator>Subtext Version 2.6.0.0</generator>
        <item>
            <title>Documentazione EF 7 (Beta 5)</title>
            <link>http://blogs.ugidotnet.org/pietrolibroblog/archive/2015/07/22/documentazione-ef-7-beta-5.aspx</link>
            <description>Documentazione "Work in Progress" della prossima release di Entity Framework : http://ef.readthedocs.org/en/latest/&lt;img src="http://blogs.ugidotnet.org/pietrolibroblog/aggbug/102030.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/pietrolibroblog/archive/2015/07/22/documentazione-ef-7-beta-5.aspx</guid>
            <pubDate>Wed, 22 Jul 2015 09:07:28 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/pietrolibroblog/archive/2015/07/22/documentazione-ef-7-beta-5.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/pietrolibroblog/comments/commentRss/102030.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/pietrolibroblog/services/trackbacks/102030.aspx</trackback:ping>
        </item>
        <item>
            <title>EF 6.1 : What&amp;rsquo;s new (3)</title>
            <link>http://blogs.ugidotnet.org/pietrolibroblog/archive/2014/03/27/ef-6.1-whatrsquos-new-3.aspx</link>
            <description>Supporto a “.ToString()” e “String.Concat()”, un esempio:  var queryConcat = from c in db.Vehicles
            where string.Concat(c.EngineSize, c.HP).Equals("1600110")
            select c;

var queryToString = from c in db.Vehicles
            where  c.HP.ToString().Equals("110")
            select c;


 

Abbiamo due Query LINQ che filtrano i dati in base a condizioni su stringhe, la prima “tira fuori” tutti i veicoli dove la concatenazione dei valori delle proprietà “EngineSize” e “HP” è uguale a “1600110”, mentre la seconda esegue un filtro su di un valore intero convertio in stringa. Se proviamo ad eseguire il codice in un ambiente con EF 6.0 otteniamo un’eccezione a runtime in tutti e due i casi:



Con EF 6.1 le query sono eseguite correttamente:



Cosa succede dietro le quinte:

SELECT 
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        COUNT(1) AS [A1]
        FROM [DomusDotNet].[Vehicles] AS [Extent1]
        WHERE N'1600110' = (CASE WHEN ([Extent1].[EngineSize] IS NULL) THEN N'' ELSE [Extent1].[EngineSize] END +  CAST( [Extent1].[HP] AS nvarchar(max)))
    )  AS [GroupBy1]

SELECT 
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        COUNT(1) AS [A1]
        FROM [DomusDotNet].[Vehicles] AS [Extent1]
        WHERE N'110' =  CAST( [Extent1].[HP] AS nvarchar(max))
    )  AS [GroupBy1]




Da analizzare il funzionamento di “String.Concat(…)” con SQL Server 2012 per verificare la conversione in SQL con la funzione “nativa SQL” “Concat”.&lt;img src="http://blogs.ugidotnet.org/pietrolibroblog/aggbug/101829.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/pietrolibroblog/archive/2014/03/27/ef-6.1-whatrsquos-new-3.aspx</guid>
            <pubDate>Thu, 27 Mar 2014 10:04:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/pietrolibroblog/archive/2014/03/27/ef-6.1-whatrsquos-new-3.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/pietrolibroblog/comments/commentRss/101829.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/pietrolibroblog/services/trackbacks/101829.aspx</trackback:ping>
        </item>
        <item>
            <title>EF : Relazione one-to-many Table-View</title>
            <link>http://blogs.ugidotnet.org/pietrolibroblog/archive/2013/12/19/ef-relazione-one-to-many-table-view.aspx</link>
            <description>Immaginiamo di avere un database SQL Server esistente, e vogliamo utilizzare Entity Framework Code First per mappare il modello dati.   Supponendo di avere due tabelle “Items” e “Categories” in relazione come da Database Diagram seguente:    Ed una “Vista” SQL Server definita come segue:  CREATE VIEW [dbo].[VCategories]
AS
SELECT    Id, Name
FROM      Categories
WHERE     (Deleted = 0)

 


Aggiungiamo due classi C# definite in questo modo:

public class Category
{
    public int Id { get; set; }
    public string Description { get; set; }
}

 

public class Item
{
    public int Id { get; set; }
    public string Code { get; set; }
    public string Description { get; set; }

    public int CategoryId { get; set; }
    public Category Category { get; set; }
}


 

che mappiamo tramite OnModelCreating (nella classe derivata da DbContext) come segue :

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity&amp;lt;Category&amp;gt;().ToTable("VCategories")
        .Property(c =&amp;gt; c.Description).HasColumnName("Name");

    modelBuilder.Entity&amp;lt;Item&amp;gt;().ToTable("Items");
    modelBuilder.Entity&amp;lt;Item&amp;gt;().HasRequired(x =&amp;gt; x.Category)
        .WithMany().HasForeignKey(o =&amp;gt; o.CategoryId);
}


 

Per verificare il funzionamento del mapping possiamo scrivere del codice tipo:

Item item = null;

using (Db db = new Db())
{
    Console.WriteLine("Items count : {0}", db.Items.Count());

    Category category = (from c in db.Categories where c.Id == 1 select c)
        .FirstOrDefault();

    item = new Item()
    {
        Category = category,
        CategoryId = category.Id,
        Code = "Code #1",
        Description = "Description #1",
    };

    db.Items.Add(item);
    db.SaveChanges();

    Console.WriteLine("Items count : {0}", db.Items.Count());
}

using (Db db = new Db())
{
    ////Edit
    item.Description = "New Description #1.";

    db.Entry&amp;lt;Item&amp;gt;(item).State = System.Data.Entity.EntityState.Modified;                
    db.SaveChanges();

    Console.WriteLine("Items count : {0}", db.Items.Count());
}

using (Db db = new Db())
{
    ////Delete.               
    db.Entry&amp;lt;Item&amp;gt;(item).State = System.Data.Entity.EntityState.Deleted;
    db.SaveChanges();

    Console.WriteLine("Items count : {0}", db.Items.Count());
}
&lt;img src="http://blogs.ugidotnet.org/pietrolibroblog/aggbug/101747.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/pietrolibroblog/archive/2013/12/19/ef-relazione-one-to-many-table-view.aspx</guid>
            <pubDate>Thu, 19 Dec 2013 16:55:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/pietrolibroblog/archive/2013/12/19/ef-relazione-one-to-many-table-view.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/pietrolibroblog/comments/commentRss/101747.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/pietrolibroblog/services/trackbacks/101747.aspx</trackback:ping>
        </item>
        <item>
            <title>DomusDotNet : We Want Web, grazie a tutti :-)</title>
            <link>http://blogs.ugidotnet.org/pietrolibroblog/archive/2012/03/10/domusdotnet-wewantweb-grazie-a-tutti.aspx</link>
            <description>Ieri 9/3/12 si è svolto l’evento WeWantWeb organizzato da DomusDotNet presso la sede Microsoft di Roma. Le sessioni sono state registrare e quanto prima pubblicheremo Slide, codice sorgente degli esempi e Video, sul sito di DomusDotNet. Grazie a tutti i partecipanti!!! Attendiamo i vostri feedback! Al prossimo evento .    Da sinistra verso destra: Alessandro Mostarda e Massimo Bonanni, Giorgio Di Nardo, Nick, io , parte di coloro che hanno avuto la pazienza di ascoltarci .&lt;img src="http://blogs.ugidotnet.org/pietrolibroblog/aggbug/100854.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/pietrolibroblog/archive/2012/03/10/domusdotnet-wewantweb-grazie-a-tutti.aspx</guid>
            <pubDate>Sat, 10 Mar 2012 20:52:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/pietrolibroblog/archive/2012/03/10/domusdotnet-wewantweb-grazie-a-tutti.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/pietrolibroblog/comments/commentRss/100854.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/pietrolibroblog/services/trackbacks/100854.aspx</trackback:ping>
        </item>
        <item>
            <title>.NET e soddisfazioni</title>
            <link>http://blogs.ugidotnet.org/pietrolibroblog/archive/2010/08/29/.net-e-soddisfazioni.aspx</link>
            <description>Dopo tanti sacrifici, ogni tanto arriva qualche soddisfazione: ieri è mi giunta  una copia del libro “Approaches in Material Sampling”, in cui, oltre ad essere uno dei coautori di un capitolo (Grazie Gianni), è presente un CD allegato con alcuni software che permettono di eseguire analisi statistiche sui dati di campionamento. Uno di questi è SISSI 2.0: “a resampling-based software for sample size determination”. Il tool è stato scritto in .NET 3.5 facendo largo uso di LINQ To Objects e programmazione multi-threading. Spero quanto prima di riuscire ad eseguire il porting verso .NET 4.0 per sfruttare MEF ed aggiungere un paio di funzionalità statistiche non presenti nella versione allegata al libro.    Maggiori dettagli sul testo sono presenti a questo indirizzo: http://www.iospress.nl/loadtop/load.php?isbn=9781607505525 mentre una versione aggiornata del software è allegata al post.  Download File - SISSI 2.0.114&lt;img src="http://blogs.ugidotnet.org/pietrolibroblog/aggbug/99123.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/pietrolibroblog/archive/2010/08/29/.net-e-soddisfazioni.aspx</guid>
            <pubDate>Sun, 29 Aug 2010 19:28:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/pietrolibroblog/archive/2010/08/29/.net-e-soddisfazioni.aspx#feedback</comments>
            <slash:comments>8</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/pietrolibroblog/comments/commentRss/99123.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/pietrolibroblog/services/trackbacks/99123.aspx</trackback:ping>
        </item>
        <item>
            <title>Estrazione di indici da una lista con LINQ</title>
            <link>http://blogs.ugidotnet.org/pietrolibroblog/archive/2009/11/27/estrazione-di-indici-da-una-lista-con-linq.aspx</link>
            <description>Se abbiamo una lista, ad esempio contenenti dei nomi, e vogliamo estrarre gli indici delle item che soddisfano una certa condizione di filtro, possiamo scrivere: 



   1:  Dim Nomi As New List(Of String)

   2:   

   3:  Nomi.Add("Antonio")

   4:  Nomi.Add("Franco")

   5:  Nomi.Add("Giovanni")

   6:  Nomi.Add("Antonio")

   7:   

   8:  Dim sStringaRiferimento As String = "Antonio"

   9:   

  10:  Dim q As IEnumerable(Of Integer) = Nomi.Select( _

  11:  	Function(nome, indice) New With {nome, indice}) _

  12:  	.Where(Function(item) item.nome.Equals(sStringaRiferimento)) _

  13:  	.Select(Function(item) item.indice)


O meglio:



  1:  Dim q1 = Nomi.Select(Function(v, i) RicercaNome(v, "Antonio", i)).Where(Function(i) i &amp;gt;= 0) 


Dove la funzione RicercaNome, è così definita: 



  1:  Private Function RicercaNome(ByVal a As String, ByVal b As String, ByVal c As Integer) As Integer

  2:     If (a.Equals(b)) Then 

  3:        Return c 

  4:     Else 

  5:        Return -1 

  6:     End If 

  7:  End Function

&lt;img src="http://blogs.ugidotnet.org/pietrolibroblog/aggbug/97619.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/pietrolibroblog/archive/2009/11/27/estrazione-di-indici-da-una-lista-con-linq.aspx</guid>
            <pubDate>Fri, 27 Nov 2009 15:09:07 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/pietrolibroblog/archive/2009/11/27/estrazione-di-indici-da-una-lista-con-linq.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/pietrolibroblog/comments/commentRss/97619.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/pietrolibroblog/services/trackbacks/97619.aspx</trackback:ping>
        </item>
        <item>
            <title>OrderBy (e OrderByDescending) e comparatori personalizzati</title>
            <link>http://blogs.ugidotnet.org/pietrolibroblog/archive/2009/01/02/orderby-e-orderbydescending-e-comparatori-personalizzati.aspx</link>
            <description>Supponiamo di lavorare con due classi del tipo seguente:     e di voler utilizzare Linq To Objects per eseguire delle operazioni sul nostro insieme di dati, composto da un array di oggetti Documento:  1 Documento[] documenti = new Documento[]{
2     new Documento ("10",new Cliente {Nome="Pietro",Cognome ="Libro",CodiceFiscale="ABA"}),
3     new Documento ("2",new Cliente {Nome="Pietro",Cognome ="Bianchi",CodiceFiscale="ABB"}),
4     new Documento ("1",new Cliente {Nome="Giuseppe",Cognome ="Rossi",CodiceFiscale="ABC"}),
5     new Documento ("1",new Cliente {Nome="Gabriele",Cognome ="Bianchi",CodiceFiscale="ABD"})};

Supponiamo di voler utilizzare una query expression per ottenere una lista (nello specifico un  oggetto che implementi l'interfaccia IEnumerable&amp;lt;T&amp;gt;, o IOrderedEnumerable&amp;lt;T&amp;gt; che estende IEnumerable&amp;lt;t&amp;gt;), che possa essere "esplorata" mediante uno statement foreach:


  1 var result =
2     from d in documenti
3     orderby d.Numero
4     select d;


Eseguendo il tutto in un'applicazione console otterremmo:

 

Che non è proprio quello che ci aspettiamo dato che 2 viene prima di 10. Il problema nasce dal fatto che nel nostro modello ad oggetti, abbiamo definito il campo Numero, della classe Documento, come String. A questo punto potremmo optare tra almeno due soluzioni: procediamo con un refactoring del codice e cambiamo il tipo del membro Numero, o utilizziamo un overload dell'Extension Method OrderBy (o OrderByDescending). Più precisamente, utilizzeremo l'overload  seguente:


  1 public static IOrderedEnumerable&amp;lt;TSource&amp;gt; OrderBy&amp;lt;TSource, TKey&amp;gt;(
2     this IEnumerable&amp;lt;TSource&amp;gt; source,
3     Func&amp;lt;TSource, TKey&amp;gt; keySelector,
4     IComparer&amp;lt;TKey&amp;gt; comparer
5 )
6 


Il quale esegue l'ordinamento  ascendente di una sequenza di dati utilizzando uno specifico Comparer. Nello specifico, questo sarà così definito:

 1 public  class DocumentoComparer : IComparer&amp;lt;Documento&amp;gt;
 2 {
 3     #region IComparer&amp;lt;Documento&amp;gt; Members
 4 
 5     public int Compare(Documento x, Documento y)
 6     {
 7         if (x.Numero.Equals(y.Numero))
 8         {
 9             //Ordina in base al nominativo del cliente
10             return string.Compare(x.Cliente.Cognome, y.Cliente.Cognome);
11         }
12         else
13         {
14             if (int.Parse(x.Numero) &amp;lt; int.Parse(y.Numero))
15                 return -1;
16             else
17                 return 1;
18         }
19     }
20 
21     #endregion
22 }

Nel caso in cui siano presenti due documenti con lo stesso numero, magari perchè di tipo diverso, l'ordinamento viene effettuato in base all'ordinamento lessicografico della proprietà Cognome del Cliente, altrimenti le stringhe Numero sono convertite nei rispettivi valori interi, quindi eseguito il confronto.

A questo punto, mediante method syntax, possiamo scrivere:

1 var resultMethod =
2     documenti
3     .OrderBy(d =&amp;gt; d, new DocumentoComparer());

Ottenendo:

 

Nel caso in cui non sia fornito un comparatore o che Comparer sia nullo verrà utilizzata la proprietà Default, di Comparer&amp;lt;T&amp;gt;, ovvero Comparer&amp;lt;TKey&amp;gt;.Default, ma se il tipo T (come ad esempio Documento) non implementa ne l'interfaccia IComparable&amp;lt;T&amp;gt; ne IComparable, in fase di esecuzione verrà generata un'eccezione.

Technorati Tag: Linq To Objects,OrderBy,OrderByDescending&lt;img src="http://blogs.ugidotnet.org/pietrolibroblog/aggbug/95080.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/pietrolibroblog/archive/2009/01/02/orderby-e-orderbydescending-e-comparatori-personalizzati.aspx</guid>
            <pubDate>Fri, 02 Jan 2009 20:58:43 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/pietrolibroblog/archive/2009/01/02/orderby-e-orderbydescending-e-comparatori-personalizzati.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/pietrolibroblog/comments/commentRss/95080.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/pietrolibroblog/services/trackbacks/95080.aspx</trackback:ping>
        </item>
        <item>
            <title>Passato e presente</title>
            <link>http://blogs.ugidotnet.org/pietrolibroblog/archive/2008/10/21/94313.aspx</link>
            <description>Mi trovavo ad analizzare un vecchio codice VB6 per un amico, ed ho trovato una possibile implementazione di un algorimo per la risoluzione del seguente problema: Dato un array di double, trovare il valore minimo, escludendo dei valori, ad esempio, (0).  Soluzione del passato trovata (VB6)     Function TrovaMinimo(dati() As Double, Optional Except As Double)

    Dim i As Integer
    Dim Minimo As Double
    Dim numerodati As Integer
        
    numerodati = UBound(dati)
        
    Minimo = dati(1)
    
    If Except &amp;lt; 0 Then
        For i = 2 To numerodati
            If dati(i) &amp;lt; Minimo Then
                Minimo = dati(i)
            End If
        Next i
    Else
        For i = 2 To numerodati
            If dati(i) &amp;lt; Minimo And dati(i) &amp;lt;&amp;gt; Except Then
                Minimo = dati(i)
            End If
        Next i
    End If
    
    TrovaMinimo = Minimo
    
End Function


Se il valore del parametro Except è minore di zero, viene trovato il minimo considerando tutti i valori nell'array, altrimenti si cerca l'elemento minimo, escludendo il valore di Except

Come potrebbe essere implementata una possibile soluzione del problema, sfruttando le tecnologie attuali:
  using System.Linq;
...

double[] data = new Double[] { 28, 25 ,0};
//Ritorna il valore minimo escludendo il valore 0
Console.WriteLine(data.Where(d =&amp;gt; d != 0).ToArray().Min().ToString("N"));
//Ritorna il valore minimo
Console.WriteLine(data.Min().ToString("N"));&lt;img src="http://blogs.ugidotnet.org/pietrolibroblog/aggbug/94313.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/pietrolibroblog/archive/2008/10/21/94313.aspx</guid>
            <pubDate>Tue, 21 Oct 2008 19:10:12 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/pietrolibroblog/archive/2008/10/21/94313.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/pietrolibroblog/comments/commentRss/94313.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/pietrolibroblog/services/trackbacks/94313.aspx</trackback:ping>
        </item>
        <item>
            <title>WPF + LINQ + CollectionViewSource = Rss Reader</title>
            <link>http://blogs.ugidotnet.org/pietrolibroblog/archive/2008/08/27/93837.aspx</link>
            <description>Questo post è nato con uno scopo diverso da quello dell'implementazione di un Rss Reader, dato che, è sufficiente cercare su internet per trovarne di belli e pronti, ma per enfatizzare alcune proprietà molto interessanti dei controlli WPF, come  la possibilità di eseguire il raggruppamento dei dati nei controlli ListBox o ListView. Piccola parentesi: per chi volesse conoscere in dettaglio le specifiche RSS 2.0 le può trovare qui. Iniziamo sviluppando un set di classi come riassunto dal seguente Class Diagram:     Nel resto dell'esempio saranno prese in considerazione solo istanze di tipo Rss e RssItem. Generalmente, senza considerare gli elementi opzionali, la struttura xml di un documento RSS è il seguente:   1 &amp;lt;rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" ...
 2   &amp;lt;channel&amp;gt;
 3     &amp;lt;title&amp;gt;Il blog di Pietro Libro&amp;lt;/title&amp;gt;
 4     &amp;lt;link&amp;gt;http://blogs.ugidotnet.org/PietroLibroBlog/Default.aspx&amp;lt;/link&amp;gt;
 5     &amp;lt;description /&amp;gt;
 6     &amp;lt;language&amp;gt;it-IT&amp;lt;/language&amp;gt;
 7     &amp;lt;copyright&amp;gt;Pietro Libro&amp;lt;/copyright&amp;gt;
 8     &amp;lt;managingEditor&amp;gt;&amp;lt;/managingEditor&amp;gt;
 9     &amp;lt;generator&amp;gt;Subtext Version 1.9.5.176&amp;lt;/generator&amp;gt;
10     ...
11      &amp;lt;item&amp;gt;
12       &amp;lt;title&amp;gt;Adeona, il software &amp;amp;amp;quot;salva&amp;amp;amp;quot; notebook&amp;lt;/title&amp;gt;
13       &amp;lt;category&amp;gt;OT&amp;lt;/category&amp;gt;
14       &amp;lt;category&amp;gt;Varie ed eventuali&amp;lt;/category&amp;gt;
15       &amp;lt;link&amp;gt;http://blogs.ugidotnet.org/PietroLibroBlog/archive/2008/08/26/93820.aspx&amp;lt;/link&amp;gt;
16       &amp;lt;description&amp;gt;...&amp;lt;/description&amp;gt;
17       ....
18     &amp;lt;/item&amp;gt;

Per leggere un tale documento, utilizziamo un'istanza della classe XDocument, presente nel namespace System.Xml.Linq, contenente metodi che permettono la navigazione dei nodi del documento in maniera molto semplice. Se a questo aggiungiamo la potenza di Linq, veramente c'è poco da dire. Prima di tutto creiamo un'istanza  di XDocument e leggiamo il documento passando direttamente l'uri del fornitore del feed RSS:


  1 XDocument xDocument = new XDocument();                
2 xDocument = XDocument.Load(blogUri);


Per recuperare tutti gli elementi item contenuti nel documento, utilizziamo Linq. Per far questo utilizziamo il metodo Descendants passando come parametro la stringa "Item":


  1 _items =
2     (from item in xDocument.Descendants("item")
3      select new RssItem
4      {
5          Title = item.Element("title").Value,
6          Description =item.Element ("description").Value,
7          Category = item.Element("category") == null ? "Nessuna Categoria" : item.Element("category").Value ,
8          Link = item.Element("link") == null ? "": item.Element("link").Value
9      }).ToList&amp;lt;RssItem&amp;gt;();


 _items è una lista tipizzata di oggetti RssItem.

Per presentare i dati recuperati  utilizziamo una Window WPF. Il nostro obiettivo è mostrare i dati raggruppati per categoria, ovvero ottenere qualcosa del tipo:

 

Per raggiungere il goal,  invece di utilizzare la proprietà ItemSource esposta dal controllo ListBox, utilizziamo un'istanza di oggetto di tipo CollectionViewSource la quale altro non è una che un Proxy della classe CollectionView. Quest'ultima permette di eseguire operazioni di raggruppamento, ordinamento, navigazione e ricerca su di una collezione di dati. Definiamo un'istanza di tipo CollectionViewSource nella collezione Window.Resources della nostra Window WPF:


  1 &amp;lt;CollectionViewSource x:Key="cvs"&amp;gt;
2     &amp;lt;CollectionViewSource.GroupDescriptions&amp;gt;
3         &amp;lt;PropertyGroupDescription PropertyName="Category"/&amp;gt;
4     &amp;lt;/CollectionViewSource.GroupDescriptions&amp;gt;
5 &amp;lt;/CollectionViewSource&amp;gt;


Così facendo, aggiungiamo alla collezione GroupDescriptions un oggetto di tipo GroupDescription che descrive il criterio in base al quale i  dati devono essere raggruppati nella vista, nello specifico in base al valore della proprietà Category. 

Tramite codice XAML, andiamo a descrivere come devono essere visualizzati i nostri Gruppi:

 1 &amp;lt;Style x:Key="CustomGroupStyle" TargetType="{x:Type GroupItem}"&amp;gt;
 2     &amp;lt;Setter Property="Margin" Value="0,0,0,5"/&amp;gt;
 3     &amp;lt;Setter Property="Template"&amp;gt;
 4         &amp;lt;Setter.Value&amp;gt;
 5             &amp;lt;ControlTemplate TargetType="{x:Type GroupItem}"&amp;gt;
 6                 &amp;lt;Expander IsExpanded="False" BorderBrush="#FFA4B97F" BorderThickness="0,0,0,1"&amp;gt;
 7                     &amp;lt;Expander.Header&amp;gt;
 8                         &amp;lt;DockPanel&amp;gt;
 9                             &amp;lt;TextBlock FontWeight="Bold" Text="{Binding Path=Name}"/&amp;gt;
10                             &amp;lt;TextBlock FontWeight="Bold" Text="{Binding Path=ItemCount, 
11                                     Converter={StaticResource CustomConverter},
12                                     ConverterParameter=' - Numero di post ({0}) '}"/&amp;gt;
13                         &amp;lt;/DockPanel&amp;gt;
14                     &amp;lt;/Expander.Header&amp;gt;
15                     &amp;lt;Expander.Content&amp;gt;
16                         &amp;lt;ItemsPresenter /&amp;gt;
17                     &amp;lt;/Expander.Content&amp;gt;
18                 &amp;lt;/Expander&amp;gt;
19             &amp;lt;/ControlTemplate&amp;gt;
20         &amp;lt;/Setter.Value&amp;gt;
21     &amp;lt;/Setter&amp;gt;
22 &amp;lt;/Style&amp;gt;

E gli elementi in essi contenuti:

1 &amp;lt;DataTemplate x:Key="ItemTemplate"&amp;gt;
2     &amp;lt;StackPanel&amp;gt;
3         &amp;lt;TextBlock Text="{Binding Path=Title}"&amp;gt;&amp;lt;/TextBlock&amp;gt;
4         &amp;lt;TextBlock&amp;gt;
5     &amp;lt;Hyperlink NavigateUri="{Binding Path=Link}" Click="Hyperlink_Click"&amp;gt;Visualizza&amp;lt;/Hyperlink&amp;gt;
6         &amp;lt;/TextBlock&amp;gt;
7     &amp;lt;/StackPanel&amp;gt;
8 &amp;lt;/DataTemplate&amp;gt;

Non resta che definire il controllo ListBox:


  1 &amp;lt;ListBox Name="lstBox" ItemTemplate="{StaticResource ItemTemplate}" Margin="12,41,12,12"&amp;gt;
2     &amp;lt;ListBox.GroupStyle&amp;gt;
3         &amp;lt;GroupStyle ContainerStyle="{StaticResource CustomGroupStyle}"/&amp;gt;
4     &amp;lt;/ListBox.GroupStyle&amp;gt;
5 &amp;lt;/ListBox&amp;gt;


Utilizzando un controllo Button per recuperare il contenuto del documento RSS, scriviamo il seguente codice C#:


  1 LinqRss.Rss rss = new LinqRss.Rss();
2 if (rss.Load("http://blogs.ugidotnet.org/PietroLibroBlog/Rss.aspx"))
3 {
4     CollectionViewSource collectionViewSource = this.FindResource("cvs") as CollectionViewSource ;
5     collectionViewSource.Source = rss.Items;
6     lstBox.ItemsSource = collectionViewSource.View;
7 }


In sintesi, recuperata l'istanza di CollectionViewSource contenuta nelle risorse della nostra Window WPF,  impostiamo la proprietà Source dell'oggetto CollectionViewSource utilizzando la collezione Items esposta dall'istanza Rss. Non resta che impostare la proprietà ItemSource del controllo ListBox con la proprietà View esposta da CollectionViewSource. Osservazione: i GroupItem sono costituiti da controlli Expander. Nell'ItemTemplate è presente anche un HyperLink che permette la navigazione verso il post d'interesse.

Codice C# e XAML

Technorati Tag: CollectionViewSource&lt;img src="http://blogs.ugidotnet.org/pietrolibroblog/aggbug/93837.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/pietrolibroblog/archive/2008/08/27/93837.aspx</guid>
            <pubDate>Wed, 27 Aug 2008 14:30:58 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/pietrolibroblog/archive/2008/08/27/93837.aspx#feedback</comments>
            <slash:comments>9</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/pietrolibroblog/comments/commentRss/93837.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/pietrolibroblog/services/trackbacks/93837.aspx</trackback:ping>
        </item>
        <item>
            <title>Linq: ThenBy e ThenByDescending</title>
            <link>http://blogs.ugidotnet.org/pietrolibroblog/archive/2008/05/16/92694.aspx</link>
            <description>Se abbiamo la necessità di ordinare una query Linq per più campi possiamo utilizzare gli operatori ThenBy e ThenByDescending. Considerando le classi del post precedente, se volessimo ordinare  la query:    1 var query1 = esamiSostenuti
2     .OrderBy(es =&amp;gt; es.ID_Studente)
3     .Select(es =&amp;gt; new { es.ID_Studente, es.Voto });



non solo per il campo ID_Studente, ma anche per il campo Voto, possiamo scrivere:

1 //Ordinamento Ascendente
2 var query2 = esamiSostenuti
3     .OrderBy(es =&amp;gt; es.ID_Studente)
4     .ThenBy(es =&amp;gt; es.Voto)                        
5     .Select(es =&amp;gt; new { es.ID_Studente, es.Voto });

Mentre per eseguire l'ordinamento  in modo discendente scriviamo:



1 //Ordinamento Discendente
2 var query3 = esamiSostenuti
3     .OrderBy(es =&amp;gt; es.ID_Studente)
4     .ThenByDescending(es =&amp;gt; es.Voto)
5     .Select(es =&amp;gt; new { es.ID_Studente, es.Voto });



Technorati Tag: Linq,ThenBy,ThenByDescending&lt;img src="http://blogs.ugidotnet.org/pietrolibroblog/aggbug/92694.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Pietro Libro</dc:creator>
            <guid>http://blogs.ugidotnet.org/pietrolibroblog/archive/2008/05/16/92694.aspx</guid>
            <pubDate>Fri, 16 May 2008 09:49:57 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/pietrolibroblog/archive/2008/05/16/92694.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/pietrolibroblog/comments/commentRss/92694.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/pietrolibroblog/services/trackbacks/92694.aspx</trackback:ping>
        </item>
    </channel>
</rss>