poniedziałek, 16 czerwca 2014

Wieczór z Madonną cz. 1 (Windows Phone 8.1 XAML)

Kilka uwag, jakie nasunęły mi się w związku z migracją do universal app.

1. Dalej w API WP 8.1 nie działa odczytywanie ikon z plików (np. GetThumbnailAsync ze StorageFile), i to mimo … zapewnień dokumentacji MSDN.  O niestandardowych file queries, czy wirtualizowanych wektorach dla plików znanych z Windows nie ma nawet co wspominać (to akurat zgadza się z dokumentacją)

2. AutoSuggestBox nie jest dokładnym odpowiednikiem SearchBox z Windows 8.1.  Funkcjonalnie jest to jakby TextBox, który możemy zasilić ręcznie podpowiedziami. Przycisk szukaj nie wchodzi w jego skład. Poniżej fragment view modelu, pod który podpiąłem tę kontrolkę:

        private IEnumerable<string> _suggestions;
        public IEnumerable<string> Suggestions
        {
            get
            {
                return _suggestions;
            }
            set
            {
                SetProperty<IEnumerable<string>>(ref _suggestions, value);
            }
        }

        public void GenerateSuggestions(string query)
        {
            ClearSuggestions();         

            var localSettings = ApplicationData.Current.LocalSettings;
            if (localSettings.Values.ContainsKey("VideoSuggestions"))
            {
                var data = (string)localSettings.Values["VideoSuggestions"];
                var list = JsonUtils.Deserialize<List<string>>(data);

                if (!string.IsNullOrEmpty(query))                   
                    Suggestions = list.Where(item => item.StartsWith(query)).ToList();
            }
        }

        public void ClearSuggestions()
        {
            Suggestions = null;
        }

        public async Task SearchFiles(string queryText)
        {
            var filter = !string.IsNullOrEmpty(queryText);

            if (filter)
            {
                var localSettings = ApplicationData.Current.LocalSettings;

                var list = new List<string>();
                if (localSettings.Values.ContainsKey("VideoSuggestions"))
                {
                    var data = (string)localSettings.Values["VideoSuggestions"];
                    list = JsonUtils.Deserialize<List<string>>(data);                   
                    if (!list.Contains(queryText))
                        list.Add(queryText);
                }
                else
                {
                    list.Add(queryText);
                }
                var json = JsonUtils.Serialize(list);
                localSettings.Values["VideoSuggestions"] = json;
            }
            …

       }

Jak widać zasymulowałem zachowanie Searchbox-a polegające na zapamiętywaniu wpisywanych fraz.

XAML prezentuje się następująco:

<AutoSuggestBox x:Name="searchBox"  TextChanged="searchBox_TextChanged" SuggestionChosen="searchBox_SuggestionChosen"
                        ItemsSource="{Binding Suggestions}" PlaceholderText="Search Videos"/>
<AppBarButton Grid.Column="1" Margin="0,-12,0,0" Icon="Find" Click="OnSearchButtonClicked"/>

Połączyłem go z view modelem posiłkując się wstawkami w code-behind strony (pozwoliłem sobie tym razem nie stosować bardziej ortodoksyjnego podejścia MVVM w stylu Caliburn czy Prism):

autosuggestbox

3. Korzystanie z Cortany jest bardzo przyjemne.  Oto fragment mojego pliku z komendami głosowymi:

<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.1">
 
  <CommandSet xml:lang="en-US" Name="myEnglishCommands">
    <CommandPrefix>My Movies</CommandPrefix>
    <Example>Play last</Example>

     …

    <Command Name="findVideo">
      <Example>Find Eminem</Example>
      <ListenFor>Find {text}</ListenFor>
      <Feedback>Searching for {text}</Feedback>
      <Navigate Target="Views/AddNewVideosView.xaml"/>
    </Command>   

    <PhraseTopic Label="text" Scenario="Search">
      <Subject>Music</Subject>
    </PhraseTopic>

  </CommandSet>

Wypowiadam słowa jak niżej:

cortana1

Słowa “Madonna” nie ma w definicji komend. To Cortana sama rozpoznaje (w tym przykładzie optymalnie podpowiedziałem jej by spodziewała się słowa używanego w wyszukiwarkach i związanego z muzyką, ale można też określić, by rozpoznawała dowolnie wypowiedziany tekst). Obsługując aktywację aplikacji za pomocą komendy głosowej przekierowuję na odpowiednią stronę:

        protected override void OnActivated(IActivatedEventArgs args)
        {
            Frame rootFrame = Window.Current.Content as Frame;

            if (rootFrame == null)
            {
                rootFrame = new Frame();
                SuspensionManager.RegisterFrame(rootFrame, "AppFrame");
                rootFrame.CacheSize = 1;
                Window.Current.Content = rootFrame;

                if (args.Kind != ActivationKind.VoiceCommand)
                    rootFrame.Navigate(typeof(HomeView));
            }

            Window.Current.Activate();

            base.OnActivated(args);
           
            if (args.Kind == ActivationKind.VoiceCommand)
            {
                var commandArgs = args as VoiceCommandActivatedEventArgs;
                var speechRecognitionResult = commandArgs.Result;                            
                var navigationTarget = speechRecognitionResult.SemanticInterpretation.Properties["NavigationTarget"][0];

                if (!String.IsNullOrEmpty(navigationTarget))
                {
                    Type pageType = Type.GetType(typeof(HomeView).Namespace + "." + navigationTarget.Replace("Views/","").Replace(".xaml",""));
                   
                    if (pageType != null)
                    {
                        rootFrame.Navigate(pageType, speechRecognitionResult);
                    }
                }               
            }
        }

W kodzie strony obsługuję przychodzące polecenie:

madonna

środa, 4 czerwca 2014

Visual Studio “14” CTP !

Ostatnio trafiła pod strzechy przyszła wersja Visual Studio w wersji CTP. Mamy okazję przetestować pierwszą odsłonę przyszłej wersji ASP.NET, której pokaz niedawno można było obejrzeć na TechEd. Dziś sobie zainstalowałem ten pakiet, zgodnie z sugestiami na czystym Windows, by nie mieszać z poprzednimi wersjami. Domyślnie wymagane jest 10GB, a przy instalacji wszystkiego 15GB. Więcej napiszę wkrótce, jak zrobię coś więcej niż założenie pustych, nowych projektów. Jedynie co szybko sprawdziłem, to dynamiczne odświeżanie strony Web po zmianie kodu kontrolera bez jawnej kompilacji (“Roslyn” kompiluje dynamicznie aplikację za każdym razem do pamięci bez tworzenia dll-ek w bin).

image

image

Więcej informacji na: