mercoledì 30 novembre 2011 #

Silverlight: localizzazione delle risorse

image

 

Per rendere multilingua l’interfaccia del nostro plug-in dobbiamo aggiungere al progetto Silverlight dei File di risorse contenenti le traduzioni di tutti i testi che vogliamo visualizzare.

Per localizzazione non si intende la traduzione automatica di tutti i messaggi dell’applicazione, bensì semplicemente la traduzione di tutti i testi visibili nei controlli. La traduzione dei messaggi di validazione la vedremo in un prossimo post. Pensieroso

Creiamo un nuova applicazione Silverlight:

 

 

image

 

Creiamo il nostro controllo:

 

image

    <Grid x:Name="LayoutRoot" Background="White">
        <sdk:Label Margin="25,24,0,0" Name="Label1" Content="Label1" HorizontalContentAlignment="Center" HorizontalAlignment="Left" Width="55" Height="23" VerticalAlignment="Top" d:LayoutOverrides="VerticalAlignment" />
        <TextBox Height="23" HorizontalAlignment="Left" Margin="84,20,0,0" Name="TextBox1" VerticalAlignment="Top" Width="120" HorizontalContentAlignment="Center" />
        <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="84,49,0,0" Name="Button1" VerticalAlignment="Top" Width="120" HorizontalContentAlignment="Center" />
    </Grid>

 

Andiamo ad impostare le culture (CultureInfo) che il nostro plug-in potrà identificare. Per farlo dobbiamo modificare il file di progetto. Scarichiamo il progetto e andiamo a modificarne il file .vbproj:

 

image

 

image

Identifichiamo il tag <SupportedCultures>

 <SupportedCultures>it</SupportedCultures>
 

ed aggiungiamoci le lingue desiderate:

<SupportedCultures>it;en;en-US;fr;</SupportedCultures>

In questo caso, oltre che all’italiano, abbiamo aggiunto l’inglese (en), l’inglese americano (en-US), ed il francese (fr).

Salviamo il file e ricarichiamo il progetto:

image

 

Aggiungiamo un file di risorse in cui andremo ad inserire tutte le descrizioni che vogliamo visualizzare nelle varie lingue. In Esplora Soluzioni clicchiamo col tasto destro sul nome del progetto (o in una cartella specifica), selezioniamo Aggiungi=>Nuovo elemento… ed aggiungiamo un File di risorse:

image

Apriamo il file di risorse cliccandoci sopra due volte:

image

Inseriamo due nuovi valori stringa che si riferiscono rispettivamente al testo dell’etichetta ‘Label1’ ed al testo del pulsante ‘Button1’.

Stiamo impostando i valori per la lingua di default, ossia l’italiano, quindi i valori delle stringhe dovranno essere in italiano.

Impostare come Public i marcatori d’accesso di ogni risorsa.

A questo punto è necessario crearsi una classe che ci permetta di accedere alle risorse tramite il DataBinding dei controlli.

 

image

 

Public Class myLocalization
    ' Wrapper per le risorse.
    Public ReadOnly Property Risorse_MainPage() As My.Resources.MainPage
        Get
            Return New My.Resources.MainPage
        End Get
    End Property
End Class

NB: se nel file delle risorse non avessimo impostato i marcatori su Public, non avremmo potuto accedervi dalla nostra classe.

 

Referenziamo la nostra classe all’interno del nostro plug-in importando il relativo namespace (nell’esempio lo contrassegniamo col suffisso ’my’):

<UserControl x:Class="myLocalization.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
              xmlns:my="clr-namespace:myLocalization"

Inseriamo la nostra classe nelle risorse statiche (StaticResource) dell’UserControl Silverlight:

    <UserControl.Resources>
        <my:myLocalization x:Key="myWrapperLocalization"/> <!--Imposta nelle risorse la classe per la localizzazione.-->
    </UserControl.Resources>

 

A questo punto la nostra classe (che è esposta col nome ‘myWrapperLocalization’) è accessibile da tutti i controlli contenuti all’interno dell’UserControl.

Impostiamo il binding dei controlli interessati:

- Label1 => Content

- Button1 => Content

image

Origine (Source):

image

Percorso (Path):

image

 

Questo è il risultato in XAML:

<Button Content="{Binding Path=Risorse_MainPage.Button1, Source={StaticResource myWrapperLocalization}}"

 

Una volta impostati il binding è possibile notare che nel design i controlli hanno già recuperato i valori della lingua di default:

image

 

Adesso creiamo le risorse per tutte le altre lingue che ci interessano. Copiare/Incollare il file di risorsa (.resx) che abbiamo utilizzato per la lingua di default (MainPage.resx) e traduciamo ogni singolo valore:

image

 

Rinominiamo la nostra risorsa appena tradotta in ‘MainPage.en.resex’.

 

image

 

In questo modo abbiamo creato un file di risorse per la lingua inglese.

Modifichiamo i valori delle risorse all’interno di questo file stando attenti a NON MODIFICARE le relative chiavi identificative (Nome):

Il motore delle risorse segue un ordine ben preciso nel leggere i file .resex riferiti alle culture: per primo legge il file contenente la lingua specifica, ossia quello denominato ‘nomefile.[cultura-lingua].resex’ => MainPage.en-US.resex (in questo caso l’inglese americano), se eventualmente non dovesse trovare questo file, allora legge quello riferito alla cultura generica (detta neutrale) ‘nomefile.[cultura].resex’ => MainPage.en.resex . Nel caso poi non dovesse trovare neppure il file con la cultura generica, il motore andrà a leggere il file con la lingua di default MainPage.resex .

Questa lettura gerarchica ci permette di scrivere la maggior parte delle voci multilingue nei file .resex relativi alle lingue generiche. Solo nei casi particolari si dovranno specificare le stesse voci nei file delle lingue specifiche.

Crearsi tutti i file desiderati ricordandosi di rinominare correttamente ognuno dei file .resx:

image

 

Di default Silverlight legge la lingua del sistema operativo, quindi per testare il progetto dobbiamo apportare alcune modifiche.

Possiamo testare la nostra applicazione in due modi:

  • forzare da codice la lingua del plug-in;
  • impostare la lingua del plug-in tramite la pagina web che lo ospita.

Il modo più semplice è quello di forzare la lingua del plug-in nel suo evento Application_Startup:

    Private Sub Application_Startup(ByVal o As Object, ByVal e As StartupEventArgs) Handles Me.Startup
        ' Forza la lingua.
        System.Threading.Thread.CurrentThread.CurrentUICulture = New Globalization.CultureInfo("fr")
        Me.RootVisual = New MainPage()
    End Sub

Il nostro controllo in francese:

image

 

Per impostare la lingua dalla pagina web che ospita il controllo vi rimando al post ASP.NET: passare dinamicamente un valore (o un insieme di valori) a Silverlight.

In questo modo sarà possibile testare la nostra applicazione Silverlight cambiando le impostazioni della lingua direttamente dal nostro browser:

image

 

image

 

image

 

posted @ mercoledì 30 novembre 2011 10.45 | Feedback (0)

lunedì 28 novembre 2011 #

ASP.NET: passare dinamicamente un valore (o un insieme di valori) a Silverlight.

A differenza del post precedente (ASP.NET: passare un valore statico a Silverlight), per passare dinamicamente un valore a Silverlight da una pagina .aspx, bisogna: contrassegnare il plug-in Silverlight come oggetto server, aggiungerci il parametro InitParams, contrassegnare anch’esso come oggetto server, popolare il parametro direttamente dalla pagina .aspx.

Assegnare un identificativo (id) all’oggetto Silverlight e contrassegnare il plug-in come oggetto server:

<body>
    <form id="form1" runat="server" style="height:100%">
    <div id="silverlightControlHost" runat="server">
        <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
		  <param name="source" value="ClientBin/SilverlightApplication1.xap"/>
		  <param name="onError" value="onSilverlightError" />
		  <param name="background" value="white" />
		  <param name="minRuntimeVersion" value="4.0.50826.0" />
		  <param name="autoUpgrade" value="true" />
          <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50826.0" style="text-decoration:none">
 			  <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Scarica Microsoft Silverlight" style="border-style:none"/>
		  </a>
	    </object><iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe></div>
    </form>
</body>

 

Aggiungere il parametro InitParams, contrassegnarlo come oggetto server, impostargli un identificativo e aggiungergli un attributo ‘value’ vuoto:

 

<body>
    <form id="form1" runat="server" style="height:100%">
    <div id="silverlightControlHost" runat="server">
        <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
		  <param name="source" value="ClientBin/SilverlightApplication1.xap"/>
		  <param name="onError" value="onSilverlightError" />
		  <param name="background" value="white" />
		  <param name="minRuntimeVersion" value="4.0.50826.0" />
		  <param name="autoUpgrade" value="true" />
                    <param name="initParams" id="myInitParams" runat="server" value=""/>
          <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50826.0" style="text-decoration:none">
 			  <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Scarica Microsoft Silverlight" style="border-style:none"/>
		  </a>
	    </object><iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe></div>
    </form>
</body>

 

In un qualunque evento della pagina .aspx che precede l’inizializzazione dell’oggetto Silverlight, aggiungere la coppia chiave/valore dei dati desiderati all’attributo ‘value’:

Public Class SilverlightApplication1TestPage
    Inherits System.Web.UI.Page
    Private Sub Me_Load(sender As Object, e As System.EventArgs) Handles Me.Load
        If Not IsPostBack Then
            ' Recupera le preferenze linguistiche del browser.
            Dim preferenzaCultura As String() = HttpContext.Current.Request.UserLanguages
            ' Passa il valore all'oggetto Silverlight.
            Me.myInitParams.Attributes.Add("value", "UICulture=" & preferenzaCultura(0))
        End If
    End Sub
End Class

 

Aprire il file di code-behind ‘App.xaml.vb(cs)’ e nell’Application_Startup leggere la collection InitParams:

    Private Sub Application_Startup(ByVal o As Object, ByVal e As StartupEventArgs) Handles Me.Startup
        ' Legge i parametri iniziali del pug-in.
        If e.InitParams.Count > 0 Then
            Dim cultureName As String = e.InitParams("UICulture").ToString()
            ' Imposta la lingua del browser.
            If String.IsNullOrEmpty(cultureName) = False Then
                System.Threading.Thread.CurrentThread.CurrentUICulture = New Globalization.CultureInfo(cultureName)
            End If
            ' Aggiunge il valore alle risorse.
            App.Current.Resources.Add("UICulture", System.Threading.Thread.CurrentThread.CurrentUICulture.DisplayName)
        End If
        Me.RootVisual = New MainPage()
    End Sub

In questo esempio, dalla pagina .aspx è stata passata la preferenza della lingua del browser e Silverlight l’ha impostata come propria lingua dell’applicazione.

 

image

 

E’ possibile passare dinamicamente più di un valore all’oggetto Silverlight:

Me.myInitParams.Attributes.Add("value", "chiave1=Valore1,chiave2=Valore2,Chiave3=Valore3")

 

Per un esempio completo sul passaggio di più valori leggere il post ASP.NET: passare un valore statico a Silverlight.

posted @ lunedì 28 novembre 2011 11.25 | Feedback (0)

ASP.NET: passare un valore statico a Silverlight.

Per passare a Silverlight il valore di una pagina .aspx bisogna aggiungere allo stesso plug-in il parametro <InitParams>.

Nella pagina del server identificare l’inizializzazione dell’oggetto Silverlight ed aggiungerci il seguente tag:

    <param name="initParams" value="chiave1=valore1"/>

dove l’attributo ‘value’ è il nostro valore personalizzato contrassegnato dalla chiave univoca ‘chiave1’.

<body>
    <form id="form1" runat="server" style="height:100%">
    <div id="silverlightControlHost">
        <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
		  <param name="source" value="ClientBin/SilverlightApplication1.xap"/>
		  <param name="onError" value="onSilverlightError" />
		  <param name="background" value="white" />
		  <param name="minRuntimeVersion" value="4.0.50826.0" />
		  <param name="autoUpgrade" value="true" />
                         <param name="initParams" value="chiave1=valore1"/>
		  <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50826.0" style="text-decoration:none">
 			  <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Scarica Microsoft Silverlight" style="border-style:none"/>
		  </a>
	    </object><iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe></div>
    </form>
</body>

A questo punto è possibile leggere il parametro InitParams direttamente dall’applicazione Silverlight.
Aprire il file di code-behind ‘App.xaml.vb(cs)’ e nell’Application_Startup recuperare e memorizzare nelle risorse dell’applicazione il contenuto della collection InitParams:

    Private Sub Application_Startup(ByVal o As Object, ByVal e As StartupEventArgs) Handles Me.Startup
        ' Legge i parametri iniziali del pug-in.
        Me.Resources.Add("Nuovo nome risorsa", e.InitParams("chiave1"))
        Me.RootVisual = New MainPage()
    End Sub

La collection InitParams è leggibile solamente in questa routine dell’applicazione Silverlight.

A questo punto è possibile recuperare il valore passato dalla pagina .aspx recuperandolo dalle risorse dell’applicazione:

Partial Public Class MainPage
    Inherits UserControl
    Public Sub New()
        InitializeComponent()
        Me.Label1.Content = App.Current.Resources("Nuovo nome risorsa")
    End Sub
End Class

 

image

E’ possibile inserire più di un valore nell’inizializzazione dell’oggetto Silverlight:

<param name="initParams" value="chiave1=valore1,chiave2=valore2,chiave3=valore3"/>

 

Per leggere tutti i valori impostati si dovrà ciclare l’intera collections InitParams:

    Private Sub Application_Startup(ByVal o As Object, ByVal e As StartupEventArgs) Handles Me.Startup
        ' Legge i parametri iniziali del pug-in.
        For Each p In e.InitParams
            Me.Resources.Add(p.Key, p.Value)
        Next
        Me.RootVisual = New MainPage()
    End Sub

Successivamente si potrà ciclare l’intera collection delle risorse dell’applicazione, oppure si potrà richiamare direttamente un singolo valore tramite la sua chiave identificativa:

Partial Public Class MainPage
    Inherits UserControl
    Public Sub New()
        InitializeComponent()
        For Each r In App.Current.Resources
            Me.Label1.Content &= String.Format("{0}={1}{2}", r.key, r.value, Environment.NewLine)
        Next
    End Sub
End Class

 

image

 

Abbiamo visto come passare dei valori statici all’oggetto Silverlight, ossia scrivendoli manualmente del markup della pagina .aspx in fase di progettazione della stessa. Per passare invece dei valori dinamicamente leggere il post ASP.NET: passare dinamicamente un valore (o un insieme di valori) a Silverlight.

posted @ lunedì 28 novembre 2011 10.39 | Feedback (0)

venerdì 25 novembre 2011 #

Silverlight o HTML5?

In attesa di sapere se esisterà mai una versione 6.0 di Silverlight, facciamoci due “risate”……

 

 

posted @ venerdì 25 novembre 2011 10.21 | Feedback (0)

lunedì 14 novembre 2011 #

Ciclare tutti i controlli di una pagina (WPF e Silverlight)

Per iterare tutti i gli elementi (UIElement) all'interno di una pagina di Silverlight, è possibile utilizzare

la classe VisualTreeHelper il cui metodo GetChild va richiamato in modo ricorsivo:

 

image

 

    Private Function RecuperaFigli(ByVal d As DependencyObject) _
        As IEnumerable(Of DependencyObject)

        ' Itera gli elementi in modo ricorsivo.
        Dim elementi As New List(Of DependencyObject)
        elementi.Add(d)
        For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(d) - 1
            elementi.AddRange(RecuperaFigli(VisualTreeHelper.GetChild(d, i)))
        Next

        ' Ritorna il valore.
        Return elementi
    End Function

    Private Sub MainPage_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) _
    Handles Me.Loaded

        ' Recupera tutti i controlli della pagina.
        Dim elencoControlli = Me.RecuperaFigli(Me)

        ' Visualizza l'elenco in una messagebox.
        Dim msg As String = String.Empty
        For Each u As UIElement In elencoControlli
            msg &= String.Format("{0}{1}", u.GetType.FullName, Environment.NewLine)
        Next
        MessageBox.Show(msg)
    End Sub

posted @ lunedì 14 novembre 2011 18.54 | Feedback (1)

lunedì 11 aprile 2011 #

Popolare DataGridView manualmente

Memorizzo qui un piccolo snippet per popolare manualmente una DataGridView (bound e/o unbound) in cui sono già state create le DataGridViewColumns.

  

                Dim dgvRow As New DataGridViewRow
                dgvRow.CreateCells(Me.dgvAllegati)
                With dgvRow
                    .Cells(0).Value = "valore colonna 0"
                    .Cells(1).Value = "valore colonna 1"
                    .Cells(2).Value = "valore colonna 2"
                    .Cells(3).Value = "valore colonna 3"
                End With
                Me.dgvAllegati.Rows.Add(dgvRow)

  
Questo codice è comodo se non vogliamo andare a lavorare direttamente sulla sorgente dati.

posted @ lunedì 11 aprile 2011 15.16 | Feedback (0)

martedì 9 marzo 2010 #

Web Services: impossibile caricare la sezione di configurazione endpoint

 

Lavorando (“smanettando”) coi Web Services si potrebbe incorrere nella seguente eccezione di Visual Studio:

“Impossibile caricare la sezione di configurazione endpoint per il contratto 'mio Web Service Soap'. Trovata più di una configurazione per il contratto. Indicare la sezione di configurazione endpoint preferita per nome.”

 

 

 

L’errore non sta nella configurazione del server, bensì nella configurazione dell’applicazione che deve collegarsi al Web Service.

Succede che nel file di configuazione dell’applicazione talvolta vengano generati in automatico due riferimenti uguali allo stesso Web Service.

Per correggere l’errore basta aprire il file di configurazione dell’applicazione selezionandolo da Esplora Soluzioni di Visual Studio:

 

 

 

Scorrerlo ed identificare il tag <endpoint> in cui viene configurata la chiamata al Web Service.

A questo punto è possibile notare la doppia dichiarazione:

 

 

Basterà quindi eliminare la seconda (terza, o quarta… :-P) dichiarazione per far funzionare correttamente la nostra applicazione.

 

HTH

 

PS: Perchè in italiano c’è pochissima documentazione a riguardo??…

 

Tag Cloud: ,

posted @ martedì 9 marzo 2010 15.18 | Feedback (1)

Macro per inserire immagini in Word 2007 e creare automaticamente un PDF

Sfruttando gli ultimi 2 post: Macro per utilizzare lo scanner da Word 2007 e Esportare un documento Office 2007 in PDF, ho leggermente automatizzato il procedimento aziendale di “scansione, inserimento immagni, esportazione in PDF”.

Tutta la procedura viene svolta da una semplice macro:

 

Sub Crea_PDF()
'
' Crea_PDF Macro
' Riduce i margini del foglio.
    With Selection.PageSetup
        .LineNumbering.Active = False
        .Orientation = wdOrientPortrait
        .TopMargin = CentimetersToPoints(1.27)
        .BottomMargin = CentimetersToPoints(1.27)
        .LeftMargin = CentimetersToPoints(1.27)
        .RightMargin = CentimetersToPoints(1.27)
        .Gutter = CentimetersToPoints(0)
        .HeaderDistance = CentimetersToPoints(1.25)
        .FooterDistance = CentimetersToPoints(1.25)
        .PageWidth = CentimetersToPoints(21)
        .PageHeight = CentimetersToPoints(29.7)
        .FirstPageTray = wdPrinterDefaultBin
        .OtherPagesTray = wdPrinterDefaultBin
        .SectionStart = wdSectionNewPage
        .OddAndEvenPagesHeaderFooter = False
        .DifferentFirstPageHeaderFooter = False
        .VerticalAlignment = wdAlignVerticalTop
        .SuppressEndnotes = False
        .MirrorMargins = False
        .TwoPagesOnOne = False
        .BookFoldPrinting = False
        .BookFoldRevPrinting = False
        .BookFoldPrintingSheets = 1
        .GutterPos = wdGutterPosLeft
    End With
    
' Scannerizza le immagini.
On Error Resume Next
WordBasic.InsertImagerScan
          
' Esporta in PDF.
ActiveDocument.ExportAsFixedFormat OutputFileName:= _
        "C:\Documents and Settings\Andrea\Desktop\Doc1.pdf", ExportFormat:= _
        wdExportFormatPDF, OpenAfterExport:=True, OptimizeFor:= _
        wdExportOptimizeForPrint, Range:=wdExportAllDocument, From:=1, To:=1, _
        Item:=wdExportDocumentContent, IncludeDocProps:=True, KeepIRM:=True, _
        CreateBookmarks:=wdExportCreateNoBookmarks, DocStructureTags:=True, _
        BitmapMissingFonts:=True, UseISO19005_1:=False
        
        ' Messaggio di notifica.
        MsgBox "Creazione del file PDF completata.", vbInformation, "Crea PDF"
                 
' Chiude Word chiedendo conferma.
Application.Quit

End Sub

 

NB: In questo caso il file PDF viene generato nel “C:\Documents and Settings\Andrea\Desktop”, sempre col solito nome (Doc1.pdf). Questa è una soluzione rapida per chi, come me, crea dei semplici file temporanei. E’ invece possibile personalizzare i nomi dei file inserendo ad esempio una inputbox prima dell’esportazione.

 

posted @ martedì 9 marzo 2010 10.56 | Feedback (0)

Esportare un documento Office 2007 in PDF

Per esportare un documento Office 2007 (Word, Excel) in PDF, basta installare questo componente aggiuntivo scaricabile direttamente dal sito Microsoft:

http://www.microsoft.com/downloads/details.aspx?familyid=4d951911-3e7e-4ae6-b059-a2e79ed87041&displaylang=it

Una volta installato il componente basterà poi cliccare su: Pulsante Office=>Salva con nome=>PDX o XPS.

That's all folks!

 

posted @ martedì 9 marzo 2010 10.44 | Feedback (0)

Macro per utilizzare lo scanner da Word 2007

Per scrivere una macro che utilizza lo scanner da Word 2007 basta una sola riga di codice:

 

WordBasic.InsertImagerScan

 

In questo modo, appena effettuata la scansione, l’immagine verrà inserita automaticamente all’interno del documento.

 

Tag Cloud: , ,

posted @ martedì 9 marzo 2010 10.36 | Feedback (0)

Copyright © Andrea Zingoni

Design by Bartosz Brzezinski

Design by Phil Haack Based On A Design By Bartosz Brzezinski