DanBlog

Il blog di Daniele Armanasco
posts - 37, comments - 69, trackbacks - 1

mercoledì 10 giugno 2009

Workshop: fantastico!

Non posso che confermare quanto già detto di positivo relativamente al workshop di ieri: le sessioni sono state molto interessanti e stimolanti!

Questo però me lo aspettavo, vista la qualità degli speaker che ben conoscevo (so che è brutto “dare per scontato” una qualità del genere che costa tanta preparazione, ma purtroppo la nostra “mente adattabile” si adatta anche al bello :-). Quello che invece proprio non mi aspettavo è stata la location: pienamente all’altezza dell’evento, semplicemente fantastica! Spero di vedere presto le foto di Nicolò perché le parole non rendono abbastanza …

Mi è spiaciuto non vedere tante facce note che speravo di trovare nel pubblico; spero non siano stati frenati dalla differenza di distanza rispetto a Milano perché la location la ripagava egregiamente.

Non mi resta che ringraziare Andrea & C. e ricordarmi di offrire il mio modesto contributo.

posted @ mercoledì 10 giugno 2009 0.00 | Feedback (3) |

lunedì 11 maggio 2009

Le mie prossime conf

Se qualcuno della mia zona (Brescia) vuole aggregarsi ecco l'elenco delle prossime conferenze gratuite a cui parteciperò. Per quelle di Bologna e Predappio può darsi io non ci sia per il viaggio perchè già sul posto per altri motivi; comunque se avete intenzione di partecipare fatemi sapere!

posted @ lunedì 11 maggio 2009 12.44 | Feedback (0) |

venerdì 10 aprile 2009

Prova LiveWriter

Immagine mappa

Prova generazione post da LiveWriter

posted @ venerdì 10 aprile 2009 13.21 | Feedback (0) |

sabato 7 marzo 2009

ASP.NET MVC - RedirectToAction

Nel mio primo progettino con ASP.NET MVC mi si è presentata l’esigenza di dover presentare la stessa view in due modalità diverse (diverso titolo, una con link di modifica e l’altra no, ecc.).

Ingenuamente, siccome la prima modalità (link tipo Controller/List) esisteva già, ho pensato di usare una Action di questo tipo:

        public ActionResult ViewList()

        {

            TempData["mode"] = "readonly";

            return RedirectToAction("List");

        }

delegando così tutto il lavoro di preparazione dei dati alla Action già in opera; nella pagina ho poi usato un paio di if (e si, mi capita ancora di usarli ;-)) per generare o meno i link per l’editing e per impostare il titolo.

Problema (di cui non mi sono accorto subito perché l’applicazione gira in un normale frame html che rende l’indirizzo visualizzato nella barra di IE sempre identico!): una volta eseguito RedirectToAction è come se avessi digitato quell’indirizzo (Controller/List nel mio caso) per cui se l’utente preme il pulsante Aggiorna del browser finisce nella prima modalità!

Soluzione “veloce”: ho spostato il codice presente nella prima action (Controller/List) in una funzione che richiamo da entrambe le action; la action ViewList è diventata:

        public ActionResult ViewList()

        {

            TempData["mode"] = "readonly";

            OnList_AddDataToViewData();

            return View("List");

        }

posted @ sabato 7 marzo 2009 22.25 | Feedback (0) |

User e Application Settings

In un paio di progetti a cui sto lavorando attualmente mi si è ripresentata un’esigenza classica: memorizzare certe impostazioni (come la larghezza delle colonne di una datagrid) per ogni singolo utente. Il contesto è tale per cui ogni utente utilizza in genere la stessa macchina, per cui non c’è bisogno di distribuire le impostazioni da un server, ma basta salvarle sulla macchina.

Tempo addietro avevo risolto lo stesso problema serializzando e deserializzando una mia classe di impostazioni o utilizzando uno degli application block dell’enterprise library (mi sembra si chiamasse Configuration application block).

La serializzazione ha il grosso svantaggio che se aggiungo qualche opzione alla mia classe di impostazioni il file serializzato sul pc utente non è più valido; l’application block non mi risulta più presente nella Library.

Ho quindi deciso di dare un’occhiata alla gestione di user e application setting nel framework e ne sono rimasto piacevolmente sorpreso.

In sintesi:

-          I setting di tipo application sono comuni a tutti gli utenti, mentre quelli di tipo user sono specifici di ogni utente.

-          Nelle proprietà del progetto – Settings si aggiungono tutte le impostazioni necessarie specificando lo scope User o Application.

-          L’ambiente aggiunge delle sezioni ad app.config e crea una classe Settings con una defaultInstance che ha proprietà in sola lettura per ogni impostazione con scope application e proprietà in lettura e scrittura per ogni impostazione con scope user.

        [global::System.Configuration.ApplicationScopedSettingAttribute()]

        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]

        [global::System.Configuration.DefaultSettingValueAttribute("ApplicazioneDiProva")]

        public string NomeApplicazione {

            get {

                return ((string)(this["NomeApplicazione"]));

            }

        }

       

        [global::System.Configuration.UserScopedSettingAttribute()]

        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]

        [global::System.Configuration.DefaultSettingValueAttribute("UtentePredefinitoDiProva")]

        public string NomeUtente {

            get {

                return ((string)(this["NomeUtente"]));

            }

            set {

                this["NomeUtente"] = value;

            }

        }

-          E’ possibile leggere le impostazioni user o application con la sintassi:

nomeApplicazione.Text = Settings.Default.NomeApplicazione;

nomeUtente.Text = Settings.Default.NomeUtente;

-          E’ possibile modificare le impostazioni user (non application!) così:

Settings.Default.NomeUtente = nomeUtente.Text;

Settings.Default.Save();

Il sistema salva queste impostazioni nel file user.config nella cartella AppData dell’utente.

-          E’ possibile ripristinare le impostazioni user (secondo il default salvato sia nell’app.config nella cartella del programma che nel codice della classe Settings) così:

Settings.Default.Reset();

Di tutto questo mi piacciono:

  • La semplicità (è gratis nel framework ;-));
  • La possibilità di ripristinare i valori di default;
  • Il fatto che il file delle impostazioni specifiche dell’utente viene salvato “per differenza” rispetto alle impostazioni di default e ne viene fatto il merge con le impostazioni di default; in questo modo se ad un nuovo rilascio aggiungo altre impostazioni il tutto funzionerà senza problemi mantenendo ciò che l’utente ha cambiato.

posted @ sabato 7 marzo 2009 22.19 | Feedback (0) |

giovedì 12 febbraio 2009

WPF Basic: Pulsante con immagine abilitata/disabilitata tramite stili a cascata

Ho una serie di pulsanti a cui voglio applicare un’immagine, tramite stile, che deve presentarsi in modo differente secondo che il pulsante sia abilitato o disabilitato (comportamento non automatico in WPF).

Passi:

1.       Ho creato un ResourceDictionary che contenga lo stile per tutta l’applicazione:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

 

    <!-- IMMAGINE PULSANTE -->

    <Style x:Key="ImmaginePulsante" TargetType="Image">

        <Style.Triggers>

            <!-- opacità dipendente dall'abilitazione del pulsante -->

            <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type Button}, AncestorLevel=1}, Path=IsEnabled}" Value="False">

                <Setter Property="Opacity" Value="0.20"></Setter>

            </DataTrigger>

        </Style.Triggers>       

    </Style>

    <!-- -->

   

    <!-- NAVIGATORE ============================================= -->

    <!-- pulsanti -->

    <Style x:Key="PulsanteNavigatore" TargetType="Button">

        <Setter Property="Margin" Value="1"></Setter>

        <Setter Property="Height" Value="Auto"></Setter>

        <Setter Property="Width" Value="Auto"></Setter>

    </Style>

    <!-- immagini dei pulsanti -->

    <Style x:Key="ImmagineNavigatore" BasedOn="{StaticResource ImmaginePulsante}" TargetType="Image">

        <Setter Property="Height" Value="34"></Setter>

        <Setter Property="Width" Value="34"></Setter>

        <Setter Property="Stretch" Value="Fill"></Setter>

    </Style>

    <Style x:Key="ImmaginePrimo" BasedOn="{StaticResource ImmagineNavigatore}" TargetType="Image">

        <Setter Property="Source" Value="..\Immagini\primo.png"></Setter>

    </Style>

    <Style x:Key="ImmaginePrecedente" BasedOn="{StaticResource ImmagineNavigatore}" TargetType="Image">

        <Setter Property="Source" Value="..\Immagini\precedente.png"></Setter>

    </Style>

...ecc...

</ResourceDictionary>

Nello stile si notano: il trigger che modifica l’opacità dell’immagine secondo il valore della proprietà IsEnabled del pulsante che lo contiene; la proprietà BasedOn che permette di innestare gli stili come con i css!

2.       Ho agganciato lo stile generale a tutta l’applicazione nel file Application.xaml:

    <Application.Resources>

        <ResourceDictionary>

            <ResourceDictionary.MergedDictionaries>

                <ResourceDictionary Source="Styles\GeneralStyle.xaml"></ResourceDictionary>

            </ResourceDictionary.MergedDictionaries>

        </ResourceDictionary>

    </Application.Resources>

3.       Ho applicato gli stili ai miei pulsanti e le loro immagini:

<Button Style="{StaticResource PulsanteNavigatore}" Command="{x:Static local:MyCommands.MoveFirst}" >

<Image Style="{StaticResource ImmaginePrimo}"></Image>

</Button>

<Button Style="{StaticResource PulsanteNavigatore}" Command="{x:Static local:MyCommands.MovePrevious}" >

<Image Style="{StaticResource ImmaginePrecedente}"></Image>

</Button>

posted @ giovedì 12 febbraio 2009 11.50 | Feedback (0) |

martedì 22 luglio 2008

How I got Started in Software Development

A taggatura rispondo …


A quale età hai cominciato a programmare?
How old were you when you started programming?

A 14 anni.

How did you get started in programming?
Come hai cominciato a programmare?

Mi sono fatto regalare il Commodore 64 per la Cresima ed ho iniziato a “smontare” e “rimontare” i programmi presenti nel manuale accluso; mi ci è voluto un momento per capire cosa significasse N = N +1, che dalla mia prospettiva “matematica” suonava proprio assurdo!

What was your first language?
Qual’è stato il tuo primo linguaggio di programmazione?

Basic del C64

 

What was the first real program you wrote?
Qual’è stato il primo programma vero che hai scritto?

Ricordo benissimo solo il primo che ho “copiato” dal manuale del C16 di mio cugino: doveva tracciare qualche cerchio colorato sulla televisione, ma non succedeva nulla. Dopo un’ora di verifica del codice copiato è arrivato il fratello di mio cugino e finalmente abbiamo scoperto che dovevamo digitare RUN per mandarlo in esecuzione!

 What languages have you used since you started programming?
Quali linguaggi hai usato da quando hai cominciato a programmare?

Basic, GwBasic, Assembler x86, Pascal, C, C++, VB6, VB.Net, PHP, C#

What was your first professional programming gig?
Quando è stato il tuo primo vero lavoro da programmatore?

Ho creato un programma per la stampa del catalogo, illustrato, di un’azienda di abbigliamento. A parte la solita gestione di dati anagrafici, facile in Access, c’era una piccola procedura per caricare automaticamente le fotografie degli articoli secondo una qualche logica che non ricordo.

If you knew then what you know now, would you have started programming?
Con il senno di poi, rifaresti lo stesso il programmatore? Ricominceresti a programmare?

Sì!

If there is one thing you learned along the way that you would tell new developers, what would it be?
Se ci fosse una cosa che hai imparato nella tua carriera e che vorresti dire ai giovani programmatori, cosa diresti?

Puntate in alto quando dovete scegliere quali esperienze fare; ad abbassare il tiro siete sempre in tempo ed è più facile abbassarlo che cercare di alzarlo quando ormai siete “invischiati”. Il tutto però senza esagerare e senza fare gli snob.

What's the most fun you've ever had ... programming?
Qual’è la cosa più divertente che hai programmato?

Il (piccolissimo) videogioco che sto preparando per il mio primogenito Pietro, con cui spero impari un po’ di termini inglesi. La parte più divertente è che quando avrà risposto a tutte le domande mi toccherà regalargli la wii, e visto che sono il papà mi toccherà pure giocarci!

Now, let’s tag someone else…
Adesso è l’ora di taggare qualcun’altro…

Mirco Vanini

Roberto Valenti

posted @ martedì 22 luglio 2008 7.44 | Feedback (0) |

venerdì 30 maggio 2008

Thread asincrono e pagine asp.net

Contesto: devo lanciare un'operazione che può durare molto tempo eseguita da un metodo sincrono che non torna eventi (legacy). Devo fornire un feedback all'utente (una sorta di pagina clessidra) e, a lavoro terminato, mostrare il risultato.
Soluzione adottata: creo una pagina per iniziare l'operazione e configurarne i parametri (pagina Start), una autorefreshante per comunicare che il
lavoro è in corso (pagina Wait) e una pagina per mostrare i risultati (pagina Results).
La pagina Start:
- mette in sessione un flag per indicare che il calcolo è in corso
- istanzia un delegate per richiamare il metodo sincrono con un nuovo thread;
- lancia il nuovo thread passando eventuali parametri del metodo, un riferimento al metodo di callback e un riferimento al caller stesso
- carica la pagina Wait
Il caller del MetodoLungo:
- a lavoro completato richiama il metodo di callback sulla pagina Start
Il metodo di callback (su Start):
- riaggancia il chiamante
- recupera il risultato del calcolo usando EndInvoke sul chiamante
- mette il risultato in sessione
- setta il flag in sessione per indicare che il calcolo è terminato
La pagina Wait:
- ha un tag meta (magari inserito da codice) per fare il refresh automatico
- verifica il flag in sessione per sapere quando passare alla pagina dei risultati
La pagina Results:
- recupera il risultato dalla sessione e lo mostra

Codice:
pagina Start:
   public delegate TipoRisultatoCalcoloLungo MetodoLungoAsyncCaller(TipoParametro1MetodoLungo par1,   TipoParametro2MetodoLungo par2);

    public partial class StartPage
    {
     ...
     void Toolbar1_ButtonClick(object sender, ToolbarEventArgs ea)
        {
             
Session[SessionConstants.SCAN_IN_PROGRESS] = true;

                        // Create the delegate.
                        MetodoLungoAsyncCaller caller = new MetodoLungoAsyncCaller(MetodoLungo);

                        // Initiate the asychronous call.  Include an AsyncCallback
                        // delegate representing the callback method, and the data
                        // needed to call EndInvoke.
                        IAsyncResult result = caller.BeginInvoke(valorePar1, valorePar2,
                            new AsyncCallback(CallbackMethod),
                            caller);

                        // goto to "hourglass" page
                        Response.Redirect(WebFormsConstants.WAIT_ASPX);
        }
        ...
        // Callback method
        public void CallbackMethod(IAsyncResult ar)
        {
            // Retrieve the delegate.
            MetodoLungoAsyncCaller caller = (MetodoLungoAsyncCaller)ar.AsyncState;

            // Call EndInvoke to retrieve the results.
            TipoRisultatoCalcoloLungo risultato = caller.EndInvoke(ar);
            Session[SessionConstants.RISULTATO] = risultato;
            // set flag in session to comunicate scan completed
            Session[SessionConstants.SCAN_IN_PROGRESS] = false;
         }
         ...
}

pagina Wait:
protected void Page_Load(object sender, EventArgs e)
        {
            HtmlMeta meta = new HtmlMeta();
            meta.HttpEquiv = "refresh";
            meta.Content = "10";
            Header.Controls.Add(meta);

            if ((Boolean)Session[SessionConstants.SCAN_IN_PROGRESS] == false)
                Response.Redirect(WebFormsConstants.RESULT_ASPX);

            Message1.Text = "In Progress";
        }

 

posted @ venerdì 30 maggio 2008 3.45 | Feedback (7) | Filed Under [ Scoperte di un principiante ]

Meta tag per refresh automatico pagina

Promemoria:          

            System.Web.UI.HtmlControls.HtmlMeta meta = new System.Web.UI.HtmlControls.HtmlMeta();
            meta.HttpEquiv = "refresh";
            meta.Content = "5";  // secondi
            Header.Controls.Add(meta);

posted @ venerdì 30 maggio 2008 3.30 | Feedback (2) | Filed Under [ Scoperte di un principiante ]

giovedì 27 marzo 2008

Alternativo a cosa?

Alternativo a UGI, perché no? Non perché UGI non abbia un grandissimo valore per noi, ma perché a volte affrontare gli stessi argomenti con una prospettiva diversa permette di cogliere aspetti non colti prima.
Avete mai sentito parlare di GUISA? Tanti degli argomenti affrontati non esistevano già prima? Non sono stati trattati anche su UGI? Perché creare uno UG separato? Forse per mettere a fuoco certi aspetti in modo più efficace …
E’ giusto interrogarsi se sia più sensato mantenere prospettive diverse “integrate” per non disperdere energie o se sia meglio renderle indipendenti per farle prosperare. E’ una scelta che facciamo tutti i giorni, ad esempio scegliendo se investire tutto presso un’unica banca per avere maggior potere o presso banche diverse per minimizzare il rischio in caso qualcosa vada storto.
Alternativo a UGI anche in senso organizzativo: UGI ha una gerarchia abbastanza precisa mentre UGIALT ha una struttura più “a rete”; perché non sfruttare la peculiarità di entrambi per arrivare più lontano?
La vera alternativa però penso stia nel fatto di lavorare alla “frontiera”, su ciò che non è consolidato. Questo non vuol dire non conoscere o usare ciò che è assodato, ma voler essere un po’ “ricercatori” per passione.
UGI lo ha sempre fatto? Bene, però ritengo che UGI sia il riferimento generale per il mondo .net, per cui ritengo giusto tratti tutti gli argomenti, consolidati o meno e soprattutto con una prospettiva “generalista”.
Ho sempre beneficiato del “mainstream” di Microsoft, perché essendo poco esperto mi è sempre stato comodo avere delle linee guida precise da seguire. Ho sempre faticato ad abbandonare questa prospettiva perché le altre alternative erano moltissime e poco omogenee; mi ha sempre spaventato il mondo open source proprio perché ti ritrovi dinnanzi un oceano di tools di cui è difficile cogliere pregi e difetti. Secondo me l’iniziativa ALT.NET cerca di colmare questa lacuna portando un po’ di “ordine” in questo oceano sterminato, vagliando e facendo poi ricadere nel “mainstream” i tools migliori. Perché privarsene? Solo perché il nome si ricollega alle esperienze che avete di persone alternative a tutti i costi? Se poi sapete che in realtà gli stessi fondatori del movimento ritenevano più adeguato il nome Pragmatic.Net e hanno lasciato Alt.net solo per “questioni storiche”, perché tante polemiche?
Non sarebbe meglio intendere alternativo come la prima o la seconda definizione del garzanti (1. che si alterna; alternato: moto alternativo, che va ora in un verso, ora in quello opposto … 2. che pone un'alternativa, una scelta) piuttosto che come la terza (3. si dice di espressione o manifestazione culturale, politica, sociale che si contrappone a quelle correnti o dominanti)?

posted @ giovedì 27 marzo 2008 11.35 | Feedback (23) |

Powered by: