Isolated Storage Serializer

Kiedy pisze się już któryś z rzędu program na daną platformę, często sięgamy do swoich poprzednich programów, żeby skopiować jakąś funkcję albo całą klasę, bo czegoś podobnego właśnie potrzebujemy. Klasa zapisana poniżej, się chyba w każdym projekcie windows phonowym. Dzięki niej za pomocą jednej metody można zserializować lub zdeserializować obiekt do/z isolated storage.

 public class IsolatedStorageSerializer<T>
    where T : class
{
    public void Serialize(T objectToSerialize, string path)
    {
        if (String.IsNullOrEmpty(path) || objectToSerialize == null)
            return;

        using (var isolated = IsolatedStorageFile.GetUserStoreForApplication())
        {
            if (isolated.FileExists(path)) isolated.DeleteFile(path);

            Stream stream = null;
            try
            {
                stream = isolated.OpenFile(path, FileMode.OpenOrCreate, FileAccess.Write);
                var serializer = new XmlSerializer(typeof(T));
                serializer.Serialize(stream, objectToSerialize);
            }
            finally
            {
                if (stream != null) stream.Close();
            }
        }
    }

    public T Deserialize(string path)
    {
        T result = null;
        if (!String.IsNullOrEmpty(path))
        {
            using (var isolated = IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (isolated.FileExists(path))
                {
                    Stream stream = null;
                    try
                    {
                        stream = isolated.OpenFile(path, FileMode.Open, FileAccess.Read);
                        var serializer = new XmlSerializer(typeof(T));
                        result = serializer.Deserialize(stream) as T;
                    }
                    finally
                    {
                        if (stream != null) stream.Close();
                    }
                }
            }
        }
        return result;
    }
}

PasswordBox z podpowiedzią w WP7

Dzisiaj kolejny post typu „skopiuj kod i działa”. Tym razem chciałbym napisać jak w WP7 zrobić PasswordBox z możliwością wpisania podpowiedzi, coś jak placeholder w htmlowych znacznikach input.

Po pierwsze będzie nam do tego potrzebny Silverlight Toolkit for Windows Phone, który daje nam fajną kontrolkę PhoneTextBox, niestety nie możemy już liczyć na PhonePasswordBox, dlatego musimy to jakoś obejść.

Efektem naszego kodu powinien być taki formularz:

Na początek w miejscu gdzie chcemy umieścić nasz passwordbox wklejamy taki oto kod:

<Grid VerticalAlignment="Top">
    <toolkit:PhoneTextBox  Name="passwordHintBox" Hint="Password" GotFocus="passwordHintBox_GotFocus" />
    <PasswordBox Name="passwordBox" Visibility="Collapsed" LostFocus="passwordBox_LostFocus"/>
</Grid>

Jak widać oba te elementy na siebie nachodzą. Przy czym w PasswordBox ustawiamy domyślnie Visibility na Collapsed, żeby nie był pokazywany w designerze, oraz przy uruchomieniu. Kluczowymi metodami, które musimy obsłużyć są GotFocus dla TextBox’a, oraz LostFocus dla PasswordBox’a.

private void passwordHintBox_GotFocus(object sender, RoutedEventArgs e)
{
    passwordHintBox.Visibility = Visibility.Collapsed;
    passwordBox.Visibility = Visibility.Visible;
    passwordBox.Focus();
}   

private void passwordBox_LostFocus(object sender, RoutedEventArgs e)
{
    if (String.IsNullOrEmpty(passwordBox.Password))
    {
        passwordBox.Visibility = Visibility.Collapsed;
        passwordHintBox.Visibility = Visibility.Visible;
    }
}

Tak więc, tłumacząc kod… jeśli użytkownik będzie chciał napisać coś w polu password, schowamy textbox z podpowiedzią, a pokażemy mu PasswordBox, od razu ustawiając na nim Focus, żeby mógł pisać. Jeśli użytkownik przestanie pisać i odznaczy kontrolkę passwordbox, sprawdzamy czy wpisał jakieś hasło, jeśli nie to ponownie pokazujemy mu textbox z podpowiedzią, jeśli coś wpisał, zostawiamy passwordbox.

Kod niby jest prosty, ale warto mieć czasami go pod ręką, żeby móc na szybko przepisać i nie głowić się, którą metodę i jak trzeba obsłużyć.

Dla Hejterów:
Żeby móc użyć kontrolki PhoneTextBox w taki sposób: toolkit:PhoneTextBox, musimy oczywiście dodać referencje i dodać przestrzeń nazw:

xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"

 

 

Kinect i Lego Mindstorms

Zapewne większość wie, co to jest kinect i że służy głównie do zabawy. Przy odrobinie umiejętności można z nim jednak zrobić znaczenie więcej. Odwiedzając stronę kinectforwindows.com możecie pobrać kompletne sdk, które pozwoli wam przerobić kinecta np na kamerkę internetową 😉 Pod tym linkiem znajdziecie więcej informacji o programowaniu kinecta.

Jak zapewne niewielu wie, lego to nie tylko klocki dla małych dzieci (nie obrażając nikogo). Lego słynie również z klocków Mindstorms, za pomocą których możemy budować różne dziwne roboty i oprogramowywać ich ruchy. Brzmi strasznie, ale programowanie takiego robota jest bardzo proste. W paczce z klockami, dostajemy program, który pozwala określać kolejność ruchów układając po kolei wirtualne klocki.

Po co o tym wszystkim mówię? Otóż jakiś czas temu na grupie .net wraz z kolegą zbudowaliśmy robota z Lego Mindstorms oraz oprogramowaliśmy go tak, żeby reagował na ruchy wykrywane przez kinecta. Oczywiście nie wystarczył nam zwykły program dołączony do klocków. Kilka osób już się pytało jak to działa, dlatego wrzuciłem kod tego programu na swoje repozytorium na GitHubie, jak ktoś chciałby przetestować lub wykorzystać ten kod w swoim projekcie to nie widzę przeszkód.
Poniżej filmik przedstawiający robota w akcji! (film kręcony kalkulatorem)

Strona logowania w Winows Phone 7

W tym poście chciałbym napisać jak w prosty sposób stworzyć stronę logowania do naszej aplikacji. Strona logowania powinna wyświetlić się tylko przy pierwszym uruchomieniu aplikacji, lub gdy użytkownik się wyloguje. Jak to zrobić, żeby przy włączaniu aplikacji nie było widać że tak na prawdę zmieniamy stronę już po wczytaniu MainPage, lub innej strony? Postaram się poprowadzić krok po kroku jak coś takiego zrobić.
Stosując się do rad zawartych poniżej, powinniście w prosty sposób takie wyświetlanie sobie zaprogramować. Zacznijmy więc od początku, tworząc nowy projekt i dodając stronę logowania.


Teraz uruchamiając aplikację otworzy się to co ustawione domyślnie czyli MainPage.xaml. Aby to zmienić musimy się zagłębić w plik WMAppManifest.xml. Zmieńmy w linijce z DefaultTask, parametr NavigationPage:

 <Tasks>
    <DefaultTask  Name ="default" NavigationPage="LoginPage.xaml"/>
 </Tasks>

Ważne żeby stroną, która znajduje się w NavigationPage nie była App.xaml ani MainPage.xaml.
Wpisanie nawet nieistniejącej strony zadziała, najbezpieczniej jest chyba jednak wpisać nazwę strony logowania.

Tak zmieniony kod będzie nam zawsze przechodził do strony LoginPage.xaml zamiast do MainPage.xaml. Nie o to nam jednak chodzi, więc aby osiągnąć swój cel musimy jeszcze dodać do zasobu aplikacji UriMappera, który później pozwoli nam przejść do odpowiedniej strony.
*W Uri musi być ta sama strona co podana wcześniej w WMAppManifest.

Mamy już obiekt UriMappera, którym możemy określić jaką stronę chcemy wywołać. Dodajmy więc do App.xaml.cs taką oto Funkcję.

void SetupUriMapper()
{
    var uriMapper = Resources["mapper"] as UriMapper;
    RootFrame.UriMapper = uriMapper;
    if (IsUserLoggedIn)
        uriMapper.UriMappings[0].MappedUri = new Uri("/MainPage.xaml", UriKind.Relative);
    else
        uriMapper.UriMappings[0].MappedUri = new Uri("/LoginPage.xaml", UriKind.Relative);
}

W tym przykładzie sprawdzam czy użytkownik jest zalogowany za pomocą flagi IsUserLoggedIn. Jeśli jest zalogowany uruchamiam MainPage, jeśli nie, uruchamiam stronę LoginPage. Zostało nam tylko dodać wywołanie tej funkcji na końcu konstruktora i aplikacja już działa.

public App()
{
    //....
    SetupUriMapper();
}

Dodatek

Na koniec jeszcze metoda, która usuwa całą historię stron poprzednich, więc jeśli użytkownik się zaloguje i aplikacja przejdzie do MainPage, powinniśmy wyczyścić kolejkę poprzednich stron, tak żeby po wciśnięciu przycisku wstecz wyjść z aplikacji, a nie powrócić do okna logowania. Tak jak mówiłem, można to zrobić za pomocą jednej linijki zapisanej w metodzie OnNavigateTo():

this.Loaded += (sender, args) => NavigationService.RemoveBackEntry();