Miroslav Holec

Miroslav Holec { Software Architect & Dev Evangelist }

miroslavholec.cz / blog / windows-phone-quick-start-tipy

Windows Phone Quick Start tipy

Miroslav Holec

Miroslav Holec

Publikován 28. února 2015 , aktualizace: 29. března 2016 |

Tento článek je starší 18 měsíců a je proto možné, že popisuje postupy nebo technologie, které v uplynulé době mohly doznat výraznějších změn. Názory a myšlenky v tomto článku již nemusí vyjadřovat současné stanovisko autora nebo autorů. Článek byl napsán 28. února 2015.

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.

.NET Core

Školení Entity Framework Core

Praktické školení pro vývojáře, během kterého se bude mít každý příležitost seznámit se základními principy, modelováním, toolingem, optimalizací dotazů a praktickým použitím v moderních webových aplikacích.

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:

  1. pro vsazení do Gridu je nutné, aby řádek Gridu měl Height="Auto" nebo Height="*"
  2. na vybrané místo pak vsadím ScrollViewer (zadám řádek Gridu kam ho chci)
  3. do něj něco nasázím pomocí StackPanelu
  4. 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 :)

Náhled Windows Phone aplikace