Sdílet prostřednictvím


Část 3: Přidání ovládacího prvku CalendarView pro UPW pomocí ostrůvků XAML

Toto je třetí část kurzu, která ukazuje, jak modernizovat ukázkovou desktopovou aplikaci WPF s názvem Contoso Expenses. Přehled kurzu, předpokladů a pokynů ke stažení ukázkové aplikace najdete v tématu Kurz: Modernizace aplikace WPF. Tento článek předpokládá, že jste už dokončili část 2.

Ve fiktivním scénáři tohoto kurzu chce vývojový tým Společnosti Contoso usnadnit volbu data pro vyúčtování výdajů na zařízení s podporou dotykového ovládání. V této části výukového programu přidáte do aplikace ovládací prvek CalendarView UWP. Jedná se o stejný ovládací prvek, který se používá v funkcích data a času systému Windows na hlavním panelu.

CalendarViewControl obrázek

Na rozdíl od ovládacího prvku InkCanvas, který jste přidali v části 2, sada Windows Community Toolkit neposkytuje zabalenou verzi CalendarView, kterou lze použít v aplikacích WPF. Alternativně budete hostovat InkCanvas v obecném ovládacím prvku WindowsXamlHost. Tento ovládací prvek můžete použít k hostování libovolného ovládacího prvku UPW první strany, který poskytuje sada Windows SDK nebo knihovna WinUI, nebo jakýkoli vlastní ovládací prvek UPW vytvořený třetí stranou. Ovládací prvek WindowsXamlHost poskytuje balíček NuGet Microsoft.Toolkit.Wpf.UI.XamlHost. Tento balíček je součástí Microsoft.Toolkit.Wpf.UI.Controls balíčku NuGet, který jste nainstalovali v části 2.

Poznámka:

Tento kurz ukazuje, jak používat WindowsXamlHost k hostování vlastního ovládacího prvku CalendarView poskytovaného Windows SDK. Návod, který ukazuje, jak hostovat vlastní ovládací prvek, naleznete v tématu Hostování vlastního ovládacího prvku UPW v aplikaci WPF pomocí ostrůvků XAML.

Abyste mohli použít ovládací prvek WindowsXamlHost , budete muset přímo volat rozhraní API WinRT z kódu v aplikaci WPF. Balíček Microsoft.Windows.SDK.Contracts NuGet obsahuje odkazy potřebné k tomu, abyste mohli volat rozhraní API WinRT z aplikace. Tento balíček je také součástí Microsoft.Toolkit.Wpf.UI.Controls balíčku NuGet, který jste nainstalovali v části 2.

Přidání ovládacího prvku WindowsXamlHost

  1. V Průzkumníku řešenírozbalte složku Zobrazení v projektu ContosoExpenses.Core a poklepejte na soubor AddNewExpense.xaml. Toto je formulář použitý k přidání nových výdajů do seznamu. Tady je, jak se to zobrazuje v aktuální verzi aplikace.

    Přidat nové výdaje

    Ovládací prvek pro výběr data, který je součástí WPF, je určený pro tradiční počítače s myší a klávesnicí. Volba data s dotykovou obrazovkou není ve skutečnosti proveditelná, a to kvůli malé velikosti ovládacího prvku a omezenému prostoru mezi jednotlivými dny v kalendáři.

  2. V horní části souboru AddNewExpense.xaml přidejte do elementu Window následující atribut.

    xmlns:xamlhost="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost"
    

    Po přidání tohoto atributu by teď měl element Window vypadat takto.

    <Window x:Class="ContosoExpenses.Views.AddNewExpense"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:xamlhost="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost"
            DataContext="{Binding Source={StaticResource ViewModelLocator},Path=AddNewExpenseViewModel}"
            xmlns:local="clr-namespace:ContosoExpenses"
            mc:Ignorable="d"
            Title="Add new expense" Height="450" Width="800"
            Background="{StaticResource AddNewExpenseBackground}">
    
  3. Změňte atribut Height elementu Window z 450 na 800. To je potřeba, protože ovládací prvek UWP CalendarView zabírá více místa než WPF výběr data.

    <Window x:Class="ContosoExpenses.Views.AddNewExpense"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:xamlhost="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost"
            DataContext="{Binding Source={StaticResource ViewModelLocator},Path=AddNewExpenseViewModel}"
            xmlns:local="clr-namespace:ContosoExpenses"
            mc:Ignorable="d"
            Title="Add new expense" Height="800" Width="800"
            Background="{StaticResource AddNewExpenseBackground}">
    
  4. DatePicker Vyhledejte prvek v dolní části souboru a nahraďte tento prvek následujícím kódem XAML.

    <xamlhost:WindowsXamlHost InitialTypeName="Windows.UI.Xaml.Controls.CalendarView" Grid.Column="1" Grid.Row="6" Margin="5, 0, 0, 0" x:Name="CalendarUwp"  />
    

    Tento XAML přidá ovládací prvek WindowsXamlHost. InitialTypeName vlastnost označuje úplný název ovládacího prvku UPW, který chcete hostovat (v tomto případě Windows.UI.Xaml.Controls.CalendarView).

  5. Stisknutím klávesy F5 sestavte a spusťte aplikaci v debuggeru. Vyberte zaměstnance ze seznamu a stiskněte tlačítko Přidat nový výdaj . Ověřte, že následující stránka obsahuje nový ovládací prvek UWP CalendarView.

    Obálka CalendarView

  6. Zavřete aplikaci.

Interagovat s ovládacím prvkem WindowsXamlHost

Dále aktualizujete aplikaci tak, aby zpracovávala vybrané datum, zobrazila ho na obrazovce a naplnila objekt Expense , který chcete uložit do databáze.

CalendarView pro UWP obsahuje dva členy, které jsou pro tento scénář relevantní:

  • Vlastnost SelectedDates obsahuje datum vybrané uživatelem.
  • Událost SelectedDatesChanged se vyvolá, když uživatel vybere datum.

Ovládací prvek WindowsXamlHost je univerzální hostitelský ovládací prvek pro jakýkoli typ ovládacího prvku UWP. Proto nezpřístupňuje vlastnost s názvem SelectedDates nebo událost s názvem SelectedDatesChanged, protože jsou specifické pro ovládací prvek CalendarView . Chcete-li získat přístup k těmto členům, musíte napsat kód, který přetypuje WindowsXamlHost na typ CalendarView . Nejlepším místem, kde to provést, je reakce na ChildChanged událost WindowsXamlHost ovládacího prvku, který je vyvolán při vykreslení hostovaného ovládacího prvku.

  1. V souboru AddNewExpense.xaml přidejte obslužnou rutinu pro událost ChildChanged ovládacího prvku WindowsXamlHost, který jste přidali dříve. Po dokončení by měl element WindowsXamlHost vypadat takto.

    <xamlhost:WindowsXamlHost InitialTypeName="Windows.UI.Xaml.Controls.CalendarView" Grid.Column="1" Grid.Row="6" Margin="5, 0, 0, 0" x:Name="CalendarUwp"  ChildChanged="CalendarUwp_ChildChanged" />
    
  2. Ve stejném souboru vyhledejte element Grid.RowDefinitions hlavní mřížky Grid. Přidejte další prvek RowDefinition s výškou , která se rovná Automatické na konci seznamu podřízených prvků. Po dokončení by měl element Grid.RowDefinitions vypadat takto (teď by mělo být 9 prvků RowDefinition).

    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    
  3. Za element WindowsXamlHost a před element Button blízko konce souboru přidejte následující XAML.

    <TextBlock Text="Selected date:" FontSize="16" FontWeight="Bold" Grid.Row="7" Grid.Column="0" />
    <TextBlock Text="{Binding Path=Date}" FontSize="16" Grid.Row="7" Grid.Column="1" />
    
  4. Vyhledejte prvek Button na konci souboru a změňte vlastnost Grid.Row z 7 na 8. Tím se tlačítko posune o jeden řádek dolů v mřížce, protože jste přidali nový řádek.

    <Button Content="Save" Grid.Row="8" Grid.Column="0" Command="{Binding Path=SaveExpenseCommand}" Margin="5, 12, 0, 0" HorizontalAlignment="Left" Width="180" />
    
  5. Otevřete soubor kódu AddNewExpense.xaml.cs .

  6. Na začátek souboru přidejte následující příkaz.

    using Microsoft.Toolkit.Wpf.UI.XamlHost;
    
  7. Do třídy AddNewExpense přidejte následující obsluhovač události. Tento kód implementuje ChildChanged událost WindowsXamlHost ovládacího prvku, který jste deklarovali dříve v souboru XAML.

    private void CalendarUwp_ChildChanged(object sender, System.EventArgs e)
    {
        WindowsXamlHost windowsXamlHost = (WindowsXamlHost)sender;
    
        Windows.UI.Xaml.Controls.CalendarView calendarView =
            (Windows.UI.Xaml.Controls.CalendarView)windowsXamlHost.Child;
    
        if (calendarView != null)
        {
            calendarView.SelectedDatesChanged += (obj, args) =>
            {
                if (args.AddedDates.Count > 0)
                {
                    Messenger.Default.Send<SelectedDateMessage>(new SelectedDateMessage(args.AddedDates[0].DateTime));
                }
            };
        }
    }
    

    Tento kód používá vlastnost Child ovládacího prvku WindowsXamlHost k přístupu k ovládacímu prvku CalendarView UWP. Kód se pak přihlásí k odběru události SelectedDatesChanged , která se aktivuje, když uživatel vybere datum z kalendáře. Tato obslužná rutina události předá vybrané datum modelu ViewModel, kde je vytvořen nový objekt Expense a uložen do databáze. K tomu kód používá infrastrukturu zasílání zpráv poskytovanou balíčkem NuGet MVVM Light. Kód odešle zprávu nazvanou SelectedDateMessage do ViewModel, který ji obdrží a nastaví vlastnost Date s vybranou hodnotou. V tomto scénáři je ovládací prvek CalendarView nakonfigurován pro režim jednoho výběru, takže kolekce bude obsahovat pouze jeden prvek.

    V tomto okamžiku projekt stále nebude kompilovat, protože chybí implementace pro SelectedDateMessage třídy. Následující kroky implementují tuto třídu.

  8. V Průzkumníku řešeníklikněte pravým tlačítkem na složku Zprávy a vyberte Přidat –> Třída. Pojmenujte novou třídu SelectedDateMessage a klikněte na Přidat.

  9. Obsah souboru kódu SelectedDateMessage.cs nahraďte následujícím kódem. Tento kód přidává příkaz using pro obor názvů GalaSoft.MvvmLight.Messaging (z balíčku MVVM Light NuGet), dědí z třídy MessageBase a přidává vlastnost DateTime, která je inicializována prostřednictvím veřejného konstruktoru. Až budete hotovi, soubor by měl vypadat takto.

    using GalaSoft.MvvmLight.Messaging;
    using System;
    
    namespace ContosoExpenses.Messages
    {
        public class SelectedDateMessage: MessageBase
        {
            public DateTime SelectedDate { get; set; }
    
            public SelectedDateMessage(DateTime selectedDate)
            {
                this.SelectedDate = selectedDate;
            }
        }
    }
    
  10. Dále aktualizujete ViewModel tak, aby obdržel tuto zprávu, a naplníte vlastnost Date ViewModelu. V Průzkumníku řešení rozbalte složku ViewModels a otevřete soubor AddNewExpenseViewModel.cs .

  11. Vyhledejte veřejný konstruktor pro AddNewExpenseViewModel třídu a na konec konstruktoru přidejte následující kód. Tento kód se zaregistruje k přijetí SelectedDateMessage, extrahuje vybrané datum z něj prostřednictvím vlastnosti SelectedDate a používá ho k nastavení vlastnosti Date poskytovanou modelem ViewModel. Vzhledem k tomu, že tato vlastnost je vázána na ovládací prvek TextBlock, který jste přidali dříve, můžete zobrazit datum vybrané uživatelem.

    Messenger.Default.Register<SelectedDateMessage>(this, message =>
    {
        Date = message.SelectedDate;
    });
    

    Po dokončení by měl konstruktor AddNewExpenseViewModel vypadat takto.

    public AddNewExpenseViewModel(IDatabaseService databaseService, IStorageService storageService)
    {
        this.databaseService = databaseService;
        this.storageService = storageService;
    
        Date = DateTime.Today;
    
        Messenger.Default.Register<SelectedDateMessage>(this, message =>
        {
            Date = message.SelectedDate;
        });
    }
    

    Poznámka:

    Metoda SaveExpenseCommand ve stejném souboru programu se stará o ukládání výdajů do databáze. Tato metoda používá Date vlastnost k vytvoření nového Expense objektu. Tato vlastnost je nyní naplněna ovládacím prvku CalendarView prostřednictvím SelectedDateMessage zprávy, kterou jste právě vytvořili.

  12. Stisknutím klávesy F5 sestavte a spusťte aplikaci v debuggeru. Vyberte jednoho z dostupných zaměstnanců a klikněte na tlačítko Přidat nový výdaj . Vyplňte všechna pole ve formuláři a zvolte datum z nového ovládacího prvku CalendarView . Ověřte, že je vybrané datum zobrazeno jako řetězec pod ovládacím prvku.

  13. Stiskněte tlačítko Uložit. Formulář bude uzavřen a nové výdaje se přidají na konec seznamu výdajů. Prvním sloupcem s datem výdajů by mělo být datum, které jste vybrali v ovládacím prvku CalendarView .

Další kroky

V tomto okamžiku kurzu jste úspěšně nahradili ovládací prvek datum a čas WPF prvkem UWP CalendarView, který kromě vstupu myši a klávesnice podporuje také dotyková a digitální pera. Přestože sada nástrojů Windows Community Toolkit neposkytuje zabalenou verzi ovládacího prvku CalendarView, který by mohl být přímo použit v aplikaci WPF, bylo možné tento ovládací prvek hostovat pomocí obecného ovládacího prvku WindowsXamlHost.

Nyní jste připraveni na část 4: Přidání uživatelských aktivit a oznámení systému Windows.