Windows Phone Quick Start tipy
Přestože jsem už neměl v plánu vytvářet žádné Windows Phone aplikace, jednu přeci jen ještě výjimečně vydám v rámci studijního předmětu MTE na FIM UHK. I když jsem si platformu Windows Phone zvolil před iOS, jelikož už mám s WP mnoho zkušeností, opět jsem narazil na celou řadu překážek, které mi vzaly mnoho času. V tomto článku popíšu několik problémů, které jsem při vývoji celkem primitivní aplikace řešil.
Architektura
Tady jsem měl od začátku jasno. Vzhledem k použití webových služeb jsem použil architekturu, kterou jsem popsal před několika měsíci v tomto článku společně s MVVM Light Toolkitem. Tady jsem poprvé narazil a udělal zásadní chybu, když jsem si stáhnul nový MVVM Light Toolkit a snažil jsem se vyvíjet WP 8.1 Silverlight aplikaci. Nefungovalo bez jakékoliv příčiny tolik věcí, že jsem se po 5 hodinách dřiny vrátil k osvědčené verzi 4.2. Kdo má hodně času a nervů, nechť si zkusí MVVM verze 5+. Za mě doporučuji:
Předávání dat mezi stránkami
Pokud uvažujete jak předávat data mezi stránkami, já to řešil tak, že při odnavigování z jedné stránky jsem si data uložil do App.xaml.cs
a při příchodu na jinou stránku jsem si tato data vyzvedl (nebo když jsem je potřeboval). Výhoda řešení je ta, že když se proklikáte na X-tou stránku a dáte back
, pořád tam ta data jsou a lze je použít.
public partial class App : Application { public static string Phrase { get; set; } public static string Phrase4List { get; set; } ...
Šlo by to asi i tak, že bych si předával parametr přes Uri:
navigationService.NavigateTo(new Uri("/Views/DetailPage.xaml?Prop=Value", UriKind.Relative));
Barvy
Osobně s tím už problém nemám ale je třeba myslet na to, že WP prostředí umožňuje nastavovat barvu pozadí a popředí. Tato barva se propisuje do vytvářených aplikací. Pokud chcete aby byla vytvářená aplikace ve stále stejných barvách (což doporučuji), pak je potřeba všechny výskyty typu {StaticResource XXX}
projít a nahradit buď vlastní barvou nebo vlastním stylem. Často totiž tyto Resources
odkazují na systémové barvy.
Textbox a klávesnice
WP umožňuje při focusu na TextBox zobrazit různé typy klávesnic. Já jsem například pro svůj slovník chtěl klávesnici s našeptáváním. Slouží k tomu vlastnost InputScope
<TextBox InputScope="Formula"/>
a ukázky co tam lze napsat jsou tady:
Tapnutí na Enter
Dále jsem chtěl, aby po tapnutí na Enter button uživatel odpálil TextBox. Řešil jsem to v XAML CodeBehindu a volal jsem si následně RelayCommand
ve ViewModelu:
private void PhraseTextBox_OnKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Enter) { NavigateTo(); } }
Metoda NavigateTo()
vypadá takto:
private void NavigateTo() { if (string.IsNullOrEmpty(PhraseTextBox.Text)) return; MainViewModel viewModel = (MainViewModel)DataContext; if (CheckDetail.IsChecked.HasValue && CheckDetail.IsChecked.Value) { App.Phrase = PhraseTextBox.Text; viewModel.NavigateToDetail(); } else { App.Phrase4List = PhraseTextBox.Text; viewModel.NavigateToList(); } }
Práce s RelayCommand
je kompletně popsaná tady:
Ikonky pro appbar
Pokud hledáte jen ty základní systémové, jsou ve složce:
C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v8.0\Icons
Složka Dark obsahuje světlé ikony pro tmavé pozadí a složka Light přesně naopak. O tom, jak vytvořit AppBar se píše v tomto článku:
ListBox a scrollování
Po třetí v životě jsem použil ListBox a potřetí v životě mi trvalo přes 2 hodiny naučit ho rozumně scrollovat. Dokázal jsem to zase metodou pokus / omyl, nicméně už zhruba vím, kde je problém. Tedy na co dávat pozor při tvorbě scrollovatelného ListBoxu:
- pro vsazení do Gridu je nutné, aby řádek Gridu měl Height="Auto" nebo Height="*"
- na vybrané místo pak vsadím ScrollViewer (zadám řádek Gridu kam ho chci)
- do něj něco nasázím pomocí StackPanelu
- a tím něco může být i ListBox a vypnutým scrollbarem (řeší to ScrollViewer)
Takže ve finále:
<Grid x:Name="LayoutRoot" > <Grid.RowDefinitions> <RowDefinition Height="*" /> </Grid.RowDefinitions> <ScrollViewer Grid.Row="0"> <StackPanel x:Name="SomePanel"> ListBox Margin="10" ItemsSource="{Binding Phrases}" ScrollViewer.VerticalScrollBarVisibility="Disabled" Width="400" HorizontalAlignment="Left"> </ListBox> </StackPanel> </ScrollViewer> </Grid>
Uvnitř ListBoxu je ještě template ale to obvykle není nic zajímavého.
Loading
Při* načítání dat z webu *jsem chtěl zobrazit nějaký progress, použil jsem ProgressBar:
<Grid.Resources> <converters:BoolToVisibilityConverter x:Key="BoolToVisibility"/> </Grid.Resources> <ProgressBar x:Name="ProgressBar" IsIndeterminate="True" Visibility="{Binding IsUpdating, Converter={StaticResource BoolToVisibility}}" Width="450" />
a jak je z kódu vidět, potřeboval jsem také* konverter Boolean hodnoty na Visibility value*:
public class BoolToVisibilityConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { bool boolean = false; if (value is bool) boolean = (bool)value; return boolean ? Visibility.Visible : Visibility.Collapsed; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return value is Visibility && (Visibility)value == Visibility.Visible; } }
PropertyChanged
Nevím proč, ale i když výše zmíněná vlastnost IsUpdating šlapala jak švýcary pomocí MVVM Light Toolkitu tímto způsobem:
private bool isUpdating; public bool IsUpdating { get { return isUpdating; } set { Set(() => IsUpdating, ref isUpdating, value); } }
jiné boolean vlastnosti mi takto nešly a vracela se mi výjimka. Vyřešil jsem to oldschool řešením:
private bool isMessageShown; public bool IsMessageShown { get { return isMessageShown; } set { if (isMessageShown == value) { return; } isMessageShown = value; RaisePropertyChanged("IsMessageShown"); } }
Barva pozadí Buttonu při OnClick
To jsem nevyřešil. Nechápu, proč Button
nemá něco jako BackgroundActive. Zkrátka když mi někdo tapne na oranžové tlačítko a drží jej dole, je modré. Progooglil jsem se desítkami webů ale řešení jsem nenašel, byť vše nasvědčuje tomu, že je potřeba někde stranou si napsat vlastní styl a ten aplikovat.
Závěr
Na to, jak málo mobilní aplikace umí jsem se celkem dost nadřel. Na to, že je to asi třetí aplikace, ve které pracuji s webovými službami jsem čekal, že jí sestavím za třetinu času, než jsem jí nakonec věnoval. Přitom 85% času jsem strávil na front endu a řešením UX. Připojuji neoficiální promo z doby prvního návrhu :)