in

dotNet Umbria

Il primo User Group in Umbria sul mondo .Net

Paolo Possanzini

April 2008 - Posts

  • WPF: Costruiamo un RSS Reader passo 3 (TreeView)

    Inseriamo la TreeView che conterrà la struttura ad albero dei feed sottoscritti.

    [code language="XML"]

    <Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:rssreader ="clr-namespace:WpfRssReader"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
        x:Class="WpfRssReader.MainForm"
        Title="Heros RSS Reader" Height="600" Width="800">

        <Grid Width="Auto" Height="Auto">
            <Grid.RowDefinitions>
                <RowDefinition Height="55"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>

            <Grid Grid.Row="1" Grid.RowSpan="1">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition Width="3*"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="96"/>
                    <RowDefinition Height="0.3*"/>
                    <RowDefinition Height="0.6*"/>
                </Grid.RowDefinitions>

                <!-- Inseriamo la TreeView che conterrà i Feeds Sottoscritti -->
                <Border Grid.Row="1" Grid.RowSpan="2" BorderBrush="#FF000000" BorderThickness="1,1,1,1" CornerRadius="4,4,4,4" Padding="4,4,4,4">
                    <TreeView Width="Auto" Height="Auto" BorderThickness="0,0,0,0" Name="tvFeedsFolders" />
                </Border>

            </Grid>
            <Rectangle Fill="#FF000000" Stroke="#FF000000" StrokeThickness="0" RadiusX="0" RadiusY="0" HorizontalAlignment="Stretch" Margin="0,0,0,0" Width="Auto"/>
            <TextBlock Margin="24,8,16,8" FontFamily="Segoe UI" FontSize="24" Foreground="#FFD5D5D5" Text="Heros {Community} RSS Reader" TextWrapping="Wrap"/>
        </Grid>
    </Window>

    [/code]

    Inseriamo un oggetto di ObjectDataProvider per preparare il Binding.
    Utilizziamo il metodo GetFeedSubTree dell'oggetto di tipo FeedHelper per popolare la TreeView

    [code language="XML"]

    <Window.Resources>
        <ObjectDataProvider x:Key="FeedTreeDS" ObjectType="{x:Type rssreader:FeedHelper}" MethodName="GetFeedSubTree" />
    </Window.Resources>

    [/code]

    A questo punto andiamo ad inserire il binding all'interno dell'oggetto TreeView

    [code language="XML"]

    <TreeView
                        ItemsSource="{Binding Source={StaticResource FeedTreeDS}}"
                        Width="Auto"
                        Height="Auto"
                        BorderThickness="0,0,0,0" Name="tvFeedsFolders" />

    [/code]

    Inseriamo subito anche un'altro Grid che con i controlli necessari a sottoscrivere i feeds, per adesso inseriamo solo due textbox, una per il nome che vogliamo dare al feed ed una per l'uri
    Posizioniamo questo nuovo Grid nella prima cella in alto a sinistra.

    [code language="XML"]

    <Grid Margin="0,0,0,0">
            <Rectangle Fill="#FFFFFFFF" Stroke="#FF000000" RadiusX="4" RadiusY="4" Margin="0,0,0,0"/>
            <TextBox Text="&lt;url&gt;" TextWrapping="Wrap" Margin="8,36,8,0" VerticalAlignment="Top" Name="txtUrl" />
            <TextBox Height="24" Text="&lt;nome&gt;" TextWrapping="Wrap" Margin="8,8,8,0" VerticalAlignment="Top" Name="txtNome" />
            <Button d:LayoutOverrides="Height" x:Name="btnSubscribe" Height="28" Content="Sottoscrivi" Click="btnSubscribe_Click" HorizontalAlignment="Right" Margin="0,0,8,8" VerticalAlignment="Bottom" Width="76"/>
        </Grid>

    [/code]

    Scriviamo il codice necessario a gestire l'evento Click del bottone che abbiamo inserito.
    Il metodo dovrà controllare qual'è il folder selezionato nella Treeview ed inserire la sottoscrizione all'interno di quel folder.
    Poi dovrà invocare il metodo FeedHelper.SubscribeFeed

    [code language="C#"]

    private void btnSubscribe_Click(object sender, RoutedEventArgs e)
    {
      TreeViewItem tvi = tvFeedsFolders.SelectedItem as TreeViewItem;
      if (tvi != null)
      {
        IFeedFolder folder = null;

        folder = tvi.Tag as IFeedFolder;
        if (folder == null)
        {
          IFeed feed = tvi.Tag as IFeed;
          if (feed != null)
          {
            folder = feed.Parent as IFeedFolder;
          }
        }

        if (folder == null)
          folder = new FeedsManagerClass().RootFolder as IFeedFolder;

        FeedHelper.SubscribeFeed(folder, txtUrl.Text, txtNome.Text);
      }
    }

    [/code]

    Ecco il risultato del lavoro svolto fino a questo momento

    image

  • WPF: Costruiamo un RSS Reader passo 2 (L'interfaccia utente)

    Come secondo passo iniziano a creare l'interfaccia utente.

    Creiamo un nuovo Windows Forms e lo chiamiamo MainForm.xaml. Ci spostiamo sul file App.xaml e impostiamo StartupUri a MainForm.xaml.
    Vediamo come creare la nostra UI. La mia idea iniziale è quella di creare un menù in alto e dividere il resto della UI in due colonne. Quella di sinistra come colonna di controllo, il resto come area di lettura dei feeds.

    [code language="XML"]

    <Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:rssreader ="clr-namespace:WpfRssReader"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
        x:Class="WpfRssReader.MainForm"
        Title="Heros RSS Reader" Height="600" Width="800">
        <Grid Width="Auto" Height="Auto">
            <Grid.RowDefinitions>
                <RowDefinition Height="55"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>

            <Rectangle Fill="#FF000000" Stroke="#FF000000" StrokeThickness="0" RadiusX="0" RadiusY="0" HorizontalAlignment="Stretch" Margin="0,0,0,0" Width="Auto"/>
            <TextBlock Margin="24,8,16,8" FontFamily="Segoe UI" FontSize="24" Foreground="#FFD5D5D5" Text="Heros {Community} RSS Reader" TextWrapping="Wrap"/>
        </Grid>
    </Window>

    [/code]

    Ho già inserito nella struttura, lo spazio dei nomi dell'applicazione e l'ho chiamata "rssreader".
    Dividiamo inoltre il form in due righe, una ad altezza fissa e una ad altezza variabile attraverso i due tag RowDefinition . Inserisco due oggetti per dare al form un leggero stile "Heros".

    Inseriamo all'interno del form un nuovo Grid che utilizzeremo come area per il posizionamento dei controlli.
    Dividiamo il Grid in righe e colonne. Dimensioniamo le colonne con un rapporto 1 a 3 utilizzando la notazione "*" e creiamo 3 righe.
    Una ad altezza fissa e due riproporzionabili.

    [code language="XML" ]

    <Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:rssreader ="clr-namespace:WpfRssReader"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
        x:Class="WpfRssReader.MainForm"
        Title="Heros RSS Reader" Height="600" Width="800">
        <Grid Width="Auto" Height="Auto">
            <Grid.RowDefinitions>
                <RowDefinition Height="55"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>

            <Grid Grid.Row="1" Grid.RowSpan="1">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition Width="3*"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="100"/>
                    <RowDefinition Height="0.3*"/>
                    <RowDefinition Height="0.6*"/>
                </Grid.RowDefinitions>
            </Grid>

            <Rectangle Fill="#FF000000" Stroke="#FF000000" StrokeThickness="0" RadiusX="0" RadiusY="0" HorizontalAlignment="Stretch" Margin="0,0,0,0" Width="Auto"/>
            <TextBlock Margin="24,8,16,8" FontFamily="Segoe UI" FontSize="24" Foreground="#FFD5D5D5" Text="Heros {Community} RSS Reader" TextWrapping="Wrap"/>
        </Grid>
    </Window>

    [/code]

    Questo è il risultato del lavoro fino a questo momento.

    image

  • WPF: Costruiamo un RSS Reader passo 1 (utilizzare Microsoft.Feeds.dll)

    Questo vuole essere il primo di una serie di articoli dedicati alla scrittura di applicazioni complete, dalla A alla Z sviluppate con il Framework 3.5, ponendo particolare attenzione al layer di presentazione attraverso WPF. Come primo esercizio creiamo un RSS reader.

    Microsoft ci mette a disposizione una libreria COM per la lettura dei Feed. La utilizzeremo in questo progetto.

    Iniziamo.

    Creiamo la nostra applicazione con VS2008 e scegliamo WPF Application come tipo di progetto.
    Per prima cosa aggiungiamo la reference alla Microsoft.Feeds.dll che possiamo trovare tra i componenti COM.

    Creiamo una classe che ci permetta di gestire in modo agevole i feeds. Chiameremo questa classe FeedHelper

    [code language="C#"]

    public static class FeedHelper
      {

        /// <summary>
        /// Get The subtree for RootFolder folder
        /// </summary>
        /// <param name="feedfolder"></param>
        /// <returns></returns>
        [Description("Get The subtree for each folder")]
        public static TreeViewItem[] GetFeedSubTree()
        {
          return GetFeedSubTree((IFeedFolder)(new FeedsManagerClass().RootFolder));
        }

        /// <summary>
        /// Get The subtree for each folder
        /// </summary>
        /// <param name="feedfolder"></param>
        /// <returns></returns>
        [Description("Get The subtree for each folder")]
        public static TreeViewItem[] GetFeedSubTree(IFeedFolder feedfolder)
        {
          try
          {

            // Creiamo una lista di nodi per questo folder
            List<TreeViewItem> result = new List<TreeViewItem>();
            foreach (IFeedFolder folder in ((IFeedsEnum)feedfolder.Subfolders))
            {
              TreeViewItem tvi = new TreeViewItem()
              {
                Header = folder.Name,
                Tag = folder,
                ItemsSource = GetFeedSubTree(folder)
              };
              result.Add(tvi);
            }

            // Creiamo i nodi anche per i feed gia scaricati.
            if (feedfolder.Feeds != null)
            {
              foreach (IFeed feed in ((IFeedsEnum)feedfolder.Feeds))
              {
                TreeViewItem tvi = new TreeViewItem()
                {
                  Header = feed.Name,
                  Tag = feed
                };

                // Esegue il download asincrono degli items presenti nel feed
                ThreadPool.QueueUserWorkItem(delegate
                {
                  try
                  {
                    feed.Download();
                  }
                  catch (Exception ex)
                  {
                    Debug.WriteLine(ex.Message);
                  }
                }, null);
                result.Add(tvi);
              }
            }

            return result.ToArray();
          }
          catch (Exception ex)
          {
            Debug.WriteLine(ex.Message);
          }
          return null;
        }

        /// <summary>
        /// Create a Feed in a foder
        /// </summary>
        /// <param name="folder"></param>
        /// <param name="uri"></param>
        /// <param name="name"></param>
        public static void SubscribeFeed(IFeedFolder folder, string uri, string name)
        {
          folder.CreateFeed(name, uri);
        }
      }

    [/code]

    Estenderemo questa classe se necessario in seguito. Per adesso ci basta porre attenzione sui due overloads GetFeedSubTree In questi due metodi viene creato in modo ricorsivo l'albero che descrive i feed sottoscritti eseguendo anche il download dei feed da ogni sottoscrizione. Da notare che non abbiamo bisogno di creare una struttura di storage dei feeds sottoscritti e scaricati. La libreria Microsoft.Feeds si occuperà di tutto per conto nostro.

  • WPF Performance Tuning

    Ho trovato un link utile a chi si diletta nello sviluppo di applicazioni WPF.
    Sono riportati tutti gli oggetti WPF che inficiano in qualche modo le performance della nostra applicazione.

    Sono riportati anche suggerimenti per migliorare le performances.

    http://blogs.msdn.com/wpfsdk/archive/2007/01/15/maximizing-wpf-3d-performance-on-tier-2-hardware.aspx

    Vi riporto inoltre il link ai tools di profiling delle performances.

    http://msdn2.microsoft.com/en-us/library/aa969767.aspx

    Un link per migliorare le nostre animazioni

    http://msdn2.microsoft.com/en-us/library/bb613592.aspx

    Un link che ci spiega come funziona il Tier della struttura grafica.

    http://msdn2.microsoft.com/en-us/library/ms742196.aspx

    Ed infine un link per risolvere i problemi dovuti all'interazione con la scheda grafica

    http://msdn2.microsoft.com/en-us/library/aa970912.aspx

  • C# ReaderWriterLock

    In .Net quando dobbiamo creare applicazioni multithread siamo soliti utilizzare l'istruzione lock per sincronizzare l'accesso alle risorse condivise.
    Questo potrebbe non essere l'approccio più corretto se si eseguono molte letture e poche scritture perchè costringiamo i vari thread ad accedere alla risorsa anche in lettura uno alla volta.

    La classe ReaderWriterLock ci aiuta a inserire i lock solo quando necessari e permette accessi multipli in lettura e accessi singoli in scrittura.
    Vi rimando ad MSDN per una trattazione dell'argomento più dettagliata.

    http://msdn2.microsoft.com/en-us/library/system.threading.readerwriterlock.aspx

    http://msdn2.microsoft.com/en-us/magazine/cc163846.aspx

  • JET4 + .Net + x64 ....

    Mi sono trovato ad utilizzare JET4 con .Net e x64...

    Diciamo che c'è qualche piccolo problema. Nelle macchine x64 infatti non esiste una versione a 64bit per i drivers JET4 (Per Itanium c'è una versione specifica)
    Quindi le nostre applicazioni compilate e ottimizzate per x64 dal compilatore JIT di .Net, non avranno a disposizione tali drivers.

    Se non potete fare altrimenti, dovete necessariamente utilizzare la versione a 32bit che è comunque presente nella macchina, ma dobbiamo forzare il compilatore a generare codice x86 e non x64 perdendo tutti i vantaggi dell'architettura x64 per la nostra applicazione. Per fare questo andiamo nelle configurazioni avanzate del progetto e spostiamo la Target CPU da Any a x86.

    Buona fortuna.

dotNet Umbria 2007-2008
Powered by Community Server (Commercial Edition), by Telligent Systems