Tips & tricks: how to handle the tombstoning and serialize relevant DataSources of application pages

When during the running state of your application, you use a chooser / launcher or you show the running tasks holding the back hardware button or you go to start and possibly start an other application, your application goes from the running state to the deactivated one and then to the dormient one and possibly to the tombstoned one.
Even thought now with mango’s new dormient state very often the data end pages of your application are preserved, this is not garanteed, so you have in your code to handle the possibility of a tombtoning, saving (during the deactivanting state) the relevant data of all your running active pages (including the scroll position and the current selected pivot item, for example).

It is possible to save the transient state of each page in the OnNavigateTo method and recover it in the OnNavigateFrom one, but a better way is to insert the proper code inside the App.xaml.cs file, in the Application_Deactivated and Application_Activated methods.
For example:

private void Application_Deactivated(object sender, DeactivatedEventArgs e) {
TransientState.Set("LoginDataSource", DataSourceManager.LoginDataSource);
TransientState.Set("LogsPivotDataSource", DataSourceManager.LogsPivotDataSource);
TransientState.Set("PanoramaPageDataSource", DataSourceManager.PanoramaPageDataSource);
TransientState.Set("SettingsPivotDataSource", DataSourceManager.SettingsPivotDataSource);
}

TO BE CONTINUED ….

Inserito in Programmazione Phone 7 | Lascia un commento

Tips and Ticks (4): how to pass Data between Pages in Windows Phone 7

  • How to pass Data between Pages in Windows Phone 7?
    There are several methods that you can use to pass Data between pages.1) The one I prefer is to store the values entered on PageTwo in a object Model that is also accessible to PageOne, possibly part of the DataSource of one of the pages.2) Other methods are to use a Global Variable defined in the App.xaml file

    public string PageTwoText { get; set; }
    

    On your PageTwo you can add a value to that variable:

    (App.Current as App).PageTwoText = txtBox.Text;
    

    and in the PageOne get it:

    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) {
         base.OnNavigatedTo(e);
         txtBlock.Text = (App.Current as App).PageTwoText;
    }
    

    3) An other method is to use a Query String: this procedure is good when we just need to share string based data between two pages. In PageOneyou cna navigate to PageTwo in this way:

    NavigationService.Navigate(new Uri("/PageTwo.xaml?Text=" + txtBox.Text + "&Number=" + oneNumber, UriKind.Relative));
    

    and in PageTwo get them:

    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) {
    	 base.OnNavigatedTo(e);
             IDictionary<string, string> parameters = this.NavigationContext.QueryString;
             if (parameters.ContainsKey("Text")){
                 txtBlock.Text = parameters["Text"];
             }
             //this is an other way to get a parameter
             string monthParam;
             if (NavigationContext.QueryString.TryGetValue("Number", out monthParam)) {
                     this.selectorDay.DataSource.SelectedItem = Convert.ToInt32(monthParam);
             }
    }
    

    4) Onother way is to use the PhoneApplicationService States: each application has one PhoneApplicationService defined in its App.xaml file. We can use this service’s property called “State”. These “States” are all transient data which means they are available only for one instant of your application which means once you restart your application these states will be lost. Also we should not try to create a new PhoneApplicationService instead we must try to use the service from the current instant.
    In PageOne you can set a state:

    protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e) {
        base.OnNavigatedTo(e);
        PhoneApplicationService.Current.State["Text"] = txtBox.Text;
    }
    

    and in PageTwo you can get it:

    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) {
        base.OnNavigatedTo(e);
        if(PhoneApplicationService.Current.State.ContainsKey("Text"))
            txtBlock.Text = (string)PhoneApplicationService.Current.State["Text"];
    }
    

    5) Last method is to use NextPage instance: whenever we call “Navigate” using a “/PageTwo.xaml”, the OnNavigatedFrom method in current page is called with event arguments with a Uri property indicating the next page and a Content property of the type of that Navigating page. So we have an opportunity to fix the set the value for next page, prior to navigating to it. In PageOne you can already set a variable of PageTwo that, after navigation, it will need to do nothing and just use it already setted variable:

    protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e) {
        base.OnNavigatedTo(e);
        if (e.Content is PageTwo) {
            (e.Content as PageTwo).txtBlock.Text = txtBox.Text;
        }
    }
    
Inserito in Programmazione Phone 7 | Lascia un commento

Il Giudice di Pace dott. Agostino Ferrau ha pronunciato la seguente sentenza …

Dopo più di due mesi dall’udienza dal Giudice di Pace e della sua sentenza a voce, eccomi arrivare finalmente per raccomandata la richiesta di ritiro della stessa negli Uffici Giudiziari di Torino.

Dal momento che è necessario presentare quella sentenza per andare a pagare la multa, con il passare ingiustificato di cotanto tempo, incominciavo a preoccuparmi!!

Se non hai letto le “puntate” precedenti sei ancora in tempo :-) : il resoconto della vicenda è tutta in http://enzocontini.wordpress.com/category/giustizia/, ed in particolare la cronistoria dettagliata e precisa dell’udienza è in http://enzocontini.wordpress.com/2011/11/23/discorso-che-avrei-voluto-fare-al-giudice-di-pace-durante-la-udienza/.

Perdiamo quindi più di mezz’ora a ritirare alle Poste la raccomandata, ci rechiamo  appena possibile per ritirare la sentenza negli Uffici Giudiziari che, ovviamente, sono aperti solo i feriali dalle 8:30 e finalmente … possiamo almeno bearci di leggere la sentenza nero su bianco!

ECCOLA!!!

REPUBBLICA ITALIANA

IN NOME DEL POPOLO ITALIANO

UFFICIO DEL GIUDICE DI PACE DI TORINO

SEZIONE V CIVILE

bla bla bla

OGGETTO: opposizione ex. articolo 22 legge 24 novembre 1981 n.689

bla bla bla

CONCLUSIONE PER L’OPPOSTA
Rigettare il ricorso in quanto infondato.

RAGIONI DI FATTO E DI DIRITTO DEL PROCESSO

bla bla bla

Si contestava, al proprietario del veicolo sanzionato per violazione del codice della strada di non aver provveduto a fornire nel termine richiesto di sessanta giorni le informazioni richieste con il suddetto verbale, trasgressione che prevedeva oltre alla sanzione pecuniaria anche la decurtazione di punti dalla patente di guida.
In particolare si sanzionava la condotta omissiva del proprietario del veicolo nell’indicare la persona alla guida del auto [NOTA MIA: lo so che sarebbe "dell'auto", ma sto riportando il testo della sentenza, errori di battitura inclusi ;-) ] sanzionata, appunto al fine della decurtazione dei punti.
Il sig. Contini mediante ricorso, ritualmente depositato presso la Cancelleria di questo giudicante, chiedeva l’annullamento del verbale di violazione dell’alticolo 126 bis, eccependo che nell’originario verbale di violazione dell’art. 158, non risultava facile a comprendere l’obbligo di doversi attivare agli incombenti di comunicazione imposti dall’art. 126 bis
[NOTA MIA: non sono state un po' troppo "sintetizzate" e "semplificate all'eccesso" le motivazioni del mio ricorso? ... almeno indicare che, a parte la poca evidenza nel testo del verbale, nel medesimo nulla viene detto per il caso assai comune in cui il trasgressore sia il proprietario del veicolo (per cui i suoi dati sono già conosciuti), ... e magari menzionare che fino all'2005 la legge stabiliva che se non si indicava altro trasgressore, di default i punti venivano tolti al possessore dell'autoveicolo e che anche questo concorre ad indurre il Cittadino a cadere involontariamente nella successiva violazione e quindi nella salata sanzione! ... e magari dire che non appena avevo ricevuto la seconda sanzione, essendo venuto a conoscenza dell'incombenza di dichiarare il trasgressore anche nel caso sia il proprietario del veicolo, ho subito inviato alla Polizia per raccomandata il foglio che attestava la mia colpevolezza!]

bla bla bla

All’udienza sopra indicata compariva il ricorrente che insisteva per l’accoglimento del ricorso e per la Polizia Municipale, già costituita in cancelleria con il deposito di comparsa, era presente il funzionario Devito.
Veniva discussa brevemente la causa [NOTA MIA: cinque minuti? ... forse meno ...] e le parti concludevano come epigrafe riportato.
Veniva quindi pronunciata la sentenza di cui si dava lettura del dispositivo.
Il ricorso non è fondato.
Si evidenzia come il verbale opposto è prodromico a precedente verbale emesso per violazione dell’articolo 158 del Cds e che le giustificazioni poste dal signor Contini sono pretestuose in quanto i verbali emessi dalla Polizia municipale di Torino, nel caso in cui si debba provvedere alle comunicazioni ex art. 126, riportano con chiarezza gli incombenti da effettuare.
[NOTA MIA: ma l'ha proprio visto bene il verbale inviato dalla Polizia per notificare la violazione in oggetto?? ... dimenticavo ... già quel Giudice di Pace, durante l'udienza, mi aveva controbattuto che ne vedeva di centinaia di quei moduli. Ma allora la "chiarezza" è una cosa veramente,  ma veramente soggettiva!! Se non ci credete, andate a vedere voi stessi di persona la "chiarezza" dei verbali in oggetto, da me scannerizzati ed allegati in http://enzocontini.wordpress.com/2011/11/23/lettera-aperta-al-sindaco-di-torino/ (in fondo)].
In ogni caso il verbale di violazione al Cds per sosta su spazio riservato agli autobus, prevedeva anche al sanzione accessioria della decurtazione dei punti dalla patente di guida.
[NOTA MIA: ma è proprio di quei punti che io con il ricorso chiedevo mi fossero decurtati, al posto della ingiusta sanzione!!!] .
In base all’articolo 126 bis, il proprietario di un veicolo nei cui confronti è stata accertata una violazione del Codice della Strada per la quale è anche prevvista la decurtazione di punti dalla patente di guida del trasgressore effettivo, ovvero della persona che al momento del rilevamento dell’infrazione, si trovava alla guida del veicolo sanzionato [NOTA MIA: ma se la macchina è parcheggiata ... nessuno si trovava ovviamente alla sua guida .... boh!!] deve comunicare chi fosse alla guida del veicolo sanzionato o in alternativa deve comunque comunicare di non essere in grado di dichiarare il nominativo del trasgressore [NOTA MIA: Ecco!!! E' qui il trucco!!!!]
In difetto, sia in caso di tardiva comunicazione, come è avvenuto nel caso di specie [NOTA MIA: meno male che si è almeno alla fine ricordato che durante l'udienza gli ho fatto notare che nel mio ricorso avevo scritto che avevo inviato la dichiarazione con il mio nominativo di trasgressore, sebbene tardivamente ma appena avevo compreso la necessità di farlo essendo io il proprietario del veicolo sanzionato, ... e avevo fatto notare anche la ricevuta del suo invio, allegata ovviamente al ricorso ... che forse non era stato letto, diciamo, con molta attenzione!], o anche in caso di attestazione di non essere in grado di riferire il nominativo del trasgressore, senza giustificato motivo, scatta obbligatoriamente la sanzione impugnata nel presente giudizio.
Rigettando il ricorso, il Giudicante, ritiene di mantenere la sanzione irrogata al minimo edittale.
Nulla si liquida per le spese del giudizio che per giuste ragioni sono compensate tra le parti, anche perchè la Pubblica Amministrazione si avvale di funzionari interni per la difesa.
bla bla bla

 

Che dirvi?

Evviva la Giustizia!!!

Inserito in Giustizia | 1 commento

Tips and Ticks (3): how to handle configuration values of an application, allowing the user to possibly these default values

  • How can be handled configuration values of an application, allowing the user to possibly change the default values here defined?
    Suppose you have defined in the App.config file some parameters assigning a predefined default value for each:
    <configuration>
      <appSettings>
        <add key="LoginType" value="DAILY" />
        <add key="MergeAudio" value="TRUE" />
    ....
      </appSettings>
    </configuration>
    

    Then you can define, for example in a Utility class, the following method: it tries to read the key from the IsolatedStorage;
    if it failes, it loads, from the configuration file, the possible default value defined by the application and then it save it in the IsolatedStorage for a quicker further use. In fact, next time that function will be called, it will find that key in the IsolatedStorage and the data will be available in less time!

            public static string GetAppSettings(string key) {
                //return (GetAppConfigString("App.config", key));
                //return null;
                String value = String.Empty;
                if (IsolatedStorageSettings.ApplicationSettings.Contains(key)) {
                    value = IsolatedStorageSettings.ApplicationSettings[key].ToString();
                } else {
                    // se non c'è nell'isolated storage: cerca di caricare, con GetAppConfigString, il valore di default (se esiste) da app.config, per poi salvarlo nell'Isolated Storage
                    value = GetAppConfigString("app.config", key);
                    if (!value.Equals(String.Empty)) {
                        SetAppSettings(key, GetAppConfigString("app.config", key));
                    }
                }
                return value;
            }
    

    Finally here it is the utility function to recover the default value of a key from the configuration file:

     private static XElement _xmlConfig;
     private static Object _xmlConfigSyncLock = new Object();
    
            public static string GetAppConfigString(string configName, string key) {
                if (_xmlConfig == null) {
                    lock (_xmlConfigSyncLock) {
                        _xmlConfig = XElement.Load(configName);
                    }
                }
                XElement element = _xmlConfig.Descendants("appSettings").Descendants("add").FirstOrDefault((el) => el.FirstAttribute.Value == key);
                if (element != null) {
                    XAttribute xAttribute = element.Attribute("value");
                    if (xAttribute != null)
                        return xAttribute.Value;
                }
                return String.Empty;
            }
    

    When you need to get the key value from your code, you can simply call

     #region App.config keys
            public const String LoginType = "LoginType";
            ...
      #endregion App.config keys
    
    string loginTypeString = Utility.GetAppSettings(Constants.LoginType);
    

    and then when the user change that default value, you can update its value in the IsolatedStorage:

    Utility.SetAppSettings(Constants.LoginType, LoginType.DAILY.ToString());
    

    where, always in the Utility class:

     public static string SetAppSettings(string key, string value) {
       IsolatedStorageSettings.ApplicationSettings[key] = value;
       IsolatedStorageSettings.ApplicationSettings.Save();
       return value;
     }
    

    Note that data written to the IsolatedStorageSettings object hasn’t actually gotten committed to the isolated storage area and it is saved only when the application that uses the class is closed. This can occur when the user closes the Web browser, refreshes a page, or browses away from the page. If you want your application to write to isolated storage immediately, you have to call the Save method in application code.

Inserito in Programmazione Phone 7 | Lascia un commento

Tips and Ticks (2) – How to handle binding in CheckBox and RadioButton

  • How to handle binding in CheckBox?
    There are several ways to do that binding but the best way I found is the following where the Click event is handled setting a specific ClickMode:
    <CheckBox x:Name="checkBoxMergeAudio" IsChecked="{Binding IsMergeAudio, Mode=TwoWay}" Margin="0,0,0,0" Click="checkBoxMergeAudio_Changed" ClickMode="Release">
         <TextBlock TextWrapping="Wrap" Text="{Binding LocalizedResources.MergeAudio, Source={StaticResource LocalizedStrings}}" />
    </CheckBox>
    

    and in the code behind:

    private void checkBoxMergeAudio_Changed(object sender, RoutedEventArgs e) {
      //save the changed state of the checkbox
      Utility.SetAppSettings(Constants.MergeAudio, (((SettingsPivotDataSource)DataContext).IsMergeAudio).ToString());
    }
    

    Note that using the TextBox style of the CheckBox, I succeded to handle also the possible wrapping of the text field of that control.

  • How to handle binding in RadioButton?
    Also in this case there are several ways! … one can be the following:
     <StackPanel Margin="0,0,0,0" Grid.Row="0" Background="{StaticResource BrushTransparentGray}">
                            <RadioButton Content="{Binding LocalizedResources.AlwaysLogin, Source={StaticResource LocalizedStrings}}" Name="alwaysLoginButton" IsChecked="{Binding LoginType, Converter={StaticResource EqualityConverter}, ConverterParameter=0, Mode=OneWay}" GroupName="AutoLoginGroup" Click="alwaysLoginButton_Checked" ClickMode="Release"  />
                            <RadioButton Content="{Binding LocalizedResources.DailyLogin, Source={StaticResource LocalizedStrings}}" Name="daylyLoginButton" IsChecked="{Binding LoginType, Converter={StaticResource EqualityConverter}, ConverterParameter=1, Mode=OneWay}"  GroupName="AutoLoginGroup" Click="daylyLoginButton_Checked" ClickMode="Release" />
                            <RadioButton Content="{Binding LocalizedResources.TimeStampLogin, Source={StaticResource LocalizedStrings}}" Name="loginEveryButton" IsChecked="{Binding LoginType, Converter={StaticResource EqualityConverter}, ConverterParameter=2, Mode=OneWay}" GroupName="AutoLoginGroup" Click="loginEveryButton_Checked" ClickMode="Release" />
    </StackPanel>
    

    and in the code behind:

     private void alwaysLoginButton_Checked(object sender, RoutedEventArgs e) {
                LoginTypeWrapper actualLoginTypeWrapper = new LoginTypeWrapper(LoginType.ALWAYS);
                if (!DataSourceManager.SettingsPivotDataSource.LoginType.Equals(actualLoginTypeWrapper)) {
                    DataSourceManager.SettingsPivotDataSource.LoginType = actualLoginTypeWrapper;
                    //salvo la nuova impostazione scelta dall'utente
                    Utility.SetAppSettings(Constants.LoginType, LoginType.ALWAYS.ToString());
                }
            }
    
            private void daylyLoginButton_Checked(object sender, RoutedEventArgs e) {
                LoginTypeWrapper actualLoginTypeWrapper = new LoginTypeWrapper(LoginType.DAILY);
                if (!DataSourceManager.SettingsPivotDataSource.LoginType.Equals(actualLoginTypeWrapper)) {
                    DataSourceManager.SettingsPivotDataSource.LoginType = actualLoginTypeWrapper;
                    //salvo la nuova impostazione scelta dall'utente
                    Utility.SetAppSettings(Constants.LoginType, LoginType.DAILY.ToString());
                }
            }
    
            private void loginEveryButton_Checked(object sender, RoutedEventArgs e) {
                LoginTypeWrapper actualLoginTypeWrapper = new LoginTypeWrapper(LoginType.EVERY);
                if (!DataSourceManager.SettingsPivotDataSource.LoginType.Equals(actualLoginTypeWrapper)) {
                    DataSourceManager.SettingsPivotDataSource.LoginType = actualLoginTypeWrapper;
                    //salvo la nuova impostazione scelta dall'utente
                    Utility.SetAppSettings(Constants.LoginType, LoginType.EVERY.ToString());
                }
            }
    

    where the converter is the following:

        public class EqualityConverter : IValueConverter {
    
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
               if (parameter != null && value is LoginTypeWrapper) {
                    if (((LoginTypeWrapper)value).Code == System.Convert.ToInt32(parameter)) {
                        return true;
                    }
                }
                return false;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
                throw new NotImplementedException();
            }
        }
    
Inserito in Programmazione Phone 7 | Lascia un commento

Tutorials & examples

Here you can find some useful link for phone 7 programming:

Inserito in Programmazione Phone 7 | Lascia un commento

Tips and Ticks (1)

  • How to force tombstoning for debug in Mango?
    In order to test your tombstoning code you can force your application to be tombstoned instead of kept in memory during debugging. To do this, just open your project properties panel, click the debug tab and check Tombstone upon deactivation while debugging.
  • How to remove a Page from backStack in Mango?
    Sometime (ex. LoginPage, DisclaimerPage) it is useful to change the back navigation normal behaviour. Before Mango the only way to change the back navigation was to use a work around like generate a QuitException (see http://www.imaginativeuniversal.com/blog/post/2010/08/22/How-to-Quit-a-WP7-Silverlight-Application.aspx). Now with Mango you can use the useful NavigationService.RemoveBackEntry() method. Unfortunately, because the backStack is a LIFO, it is possible to remove only the top entry, that is the previous page entry. So the best way to remove a page from the backStack is to use that method just in the overridden OnNavigatedFrom method of that page itself.
    protected override void OnNavigatedFrom(NavigationEventArgs e) {
      this.NavigationService.RemoveBackEntry(); //remove itself from the backStack
      base.OnNavigatedFrom(e);
    }
    

    In particular for a LoginPage (if it is not implemented as a popup window or a section of the MainPage hidden/visible properly), if the login is not always requiìred but depends from some configuration settings (ex. once a day login) it is convinent to call first the MainPage, check if the user is already authenticated in the _load method and if not call the LoginPage. A convenient flag can be used to discriminate in the OnNavigatedFrom method of the MainPage if the LoginPage is called or not and so eventually use the NavigationService.RemoveBackEntry().

    void MainPage_Loaded(object sender, RoutedEventArgs e) {
      if (!DataSourceManager.LoginDataSource.User.Authenticated) {
        //if the user is not authenticated, let's go to the LoginPage
        NavigationService.Navigate(new Uri("/LoginPage.xaml", UriKind.Relative));
        toLoginflag = true;
      } else {
        Main.Visibility = System.Windows.Visibility.Visible;
      }
    }
    
    protected override void OnNavigatedFrom(NavigationEventArgs e) {
      if (toLoginflag) {
        this.NavigationService.RemoveBackEntry(); //remove itself from the backStack
      }
    }
  • Be careful when debugging a CameraCaptureTask with a Windows Phone device!!
    You must disconnect the device from the PC if you want to try the launcher for taking a picture from your program. Otherwise, when you call the Show method of that task, the registered cameraTask_Completed event is suddenly rised with a PhotoResult.TaskResult ==TaskResult.Cancel .
  • Mango provides a build in progressbar shown in the system tray!!
    No need to use the PerformanceProgressBar of the toolkit anymore.
    You just have to add in App.cs:
    public static ProgressIndicator progInd = newProgressIndicator();
    

    and in the constructor add:

    progInd.IsIndeterminate = false; progInd.IsVisible = false;
    

    Then add in the page where you need the progressBar a method like this:

    privatevoid RunProgressBar(bool value) {
      if (value) {
        App.progInd.Text = LocalizedStrings.GetString(“Loading”);
        App.progInd.IsIndeterminate = true;
        App.progInd.IsVisible = true;
        SystemTray.SetProgressIndicator(this, App.progInd);
      }
      else {
        App.progInd.Text = null;
        App.progInd.IsIndeterminate = false;
        App.progInd.IsVisible = false;
        SystemTray.SetProgressIndicator(this, null);
      }
    }
    
  • How you can easely know how a page is navigated (for example if it is called for the first time or from a back)?
    You can override the OnNavigationTo method and test its  NavigationEventArgs parameter comparing it with the appropriate value of the NavigationMode emumeration. For example:
    if(e.NavigationMode == NavigationMode.New) { //it is called for the first time
    

    Remember that the OnNavigationTo method is called just after the page contructor and befor the possible MyPage_Load method, if you define that new RoutedEventHandler in the page contructor

     this.Loaded += newRoutedEventHandler(MyPage_Loaded);) 
  • How you can wrap a text longer than a line in the text of a CheckBox?
    You must override TextBox’s style:
    
    
  • How to play an audio recorded with Phone 7 off somewhere else (ex. on a PC)?
    If you record voice with the Microsoft.Xna.Framework.Audio.Microfone,  it just gets a PCM encoded stream of samples. Only if you use the DynamicSoundEffectInstance on the Phone 7 code the PCM encoded stream can be played also without the wav header. So, if you want to send this audio stream off somewhere else (ex. to PC Server using a web service) to be played later, it needs a proper header otherwise no PC audio player can read it. Here you can find useful code: http://damianblog.com/2011/02/07/storing-wp7-recorded-audio-as-wav-format-streams/
    If you need to merge more audio in a single one, you need to recontruct the wav header followed by the data content of each sigle audio file. Here you can find a useful link if all the wav files have the same coding: http://www.codeproject.com/Articles/15187/Concatenating-Wave-Files-Using-C-2005
  • Remember to escape the string of URI data passed in a query when you want to Navigate to an other page.
    If any of your query strings contain characters that are considered invalid in a Uri what you’re doing will fail, as you’ve discovered. You need to use Uri.EscapeDataString to escape any illegal characters first.
    The escaped strings are automatically unescaped when you read them using NavigationContext.QueryString, so there’s no need to call Uri.UnescapeDataString explicitly.
    For example:
    StringBuilder sbPage = new StringBuilder("/").Append(baseUri);
    sbPage.Append("?ID=").Append("&asset=").Append(<strong>Uri.EscapeDataString</strong>(asset.<em>Description</em>));
    NavigationService.Navigate(new Uri(sbPage.ToString(), UriKind.Relative));
    
Inserito in Programmazione Phone 7 | Lascia un commento