Руководство: Создание первого приложения WPF в Visual Studio 2019

В этой статье показано, как разработать классическое приложение Windows Presentation Foundation (WPF), которое включает элементы, являющиеся общими для большинства приложений WPF: расширяемая разметка языка разметки приложений (XAML), код программной части, определения приложений, элементы управления, макет, привязка данных и стили. Для разработки приложения вы будете использовать Visual Studio.

Важно!

Эта статья написана для платформы .NET Framework. Сведения о начале работы с .NET 7 см. в руководстве по созданию нового приложения WPF (WPF .NET).

В этом руководстве описано следующее:

  • Создание проекта WPF.
  • Использование XAML для проектирования внешнего вида пользовательского интерфейса приложения.
  • Написание кода для создания модели поведения приложения.
  • Создание управляющих определений приложения.
  • Добавление элементов управления и создание макета, образующего пользовательский интерфейс приложения.
  • Создание стилей для согласованного внешнего вида в пользовательском интерфейсе приложения.
  • Привязка пользовательского интерфейса к данным как для заполнения пользовательского интерфейса из данных, так и для синхронизации данных и пользовательского интерфейса.

Изучив данное руководство, вы сможете создать автономное приложение для Windows, которое позволит пользователям просматривать отчеты о расходах выбранных лиц. Приложение состоит из нескольких страниц WPF, размещенных в окне в стиле браузера.

Совет

Пример кода, используемый в этом руководстве, доступен как для Visual Basic, так и для C# в Руководстве по примеру кода приложения WPF.

Вы можете переключать язык примера кода между C# и Visual Basic с помощью селектора языка в верхней части этой страницы.

Необходимые компоненты

  • Visual Studio 2019 с установленной рабочей нагрузкой Разработка классических приложений .NET.

    Дополнительные сведения об установке новейшей версии Visual Studio см. в статье Установка Visual Studio.

Создание проекта приложения

Первый шаг - это создание инфраструктуры приложения, включающей в себя определение приложения, две страницы и изображение.

  1. Создайте новый проект приложения WPF на Visual Basic или Visual C# с именем ExpenseIt:

    1. Откройте Visual Studio и выберите «Создать проект» в меню «Начало работы».

      Откроется диалоговое окно «Создание нового проекта».

    2. В раскрывающемся списке «Язык» выберите C# или Visual Basic.

    3. Выберите шаблон «Приложение WPF (.NET Framework)» и нажмите Далее.

      Create a new project dialog

      Откроется диалоговое окно «Настроить новый проект».

    4. Введите имя проекта ExpenseIt и выберите Создать.

      Configure a new project dialog

      Visual Studio создаст проект и откроет конструктор для окна приложения по умолчанию, MainWindow.xaml.

  2. Откройте файл Application.xaml (Visual Basic) или файл App.xaml (C#).

    Этот файл XAML определяет приложение WPF и все его ресурсы. Он также используется для определения пользовательского интерфейса, автоматически отображаемого при запуске приложения (в данном случае — MainWindow.xaml).

    XAML должен выглядеть следующим образом в Visual Basic:

    <Application x:Class="Application"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        StartupUri="MainWindow.xaml">
        <Application.Resources>
            
        </Application.Resources>
    </Application>
    

    И как показано ниже - в C#:

    <Application x:Class="ExpenseIt.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         StartupUri="MainWindow.xaml">
        <Application.Resources>
             
        </Application.Resources>
    </Application>
    
  3. Откройте файл MainWindow.xaml.

    Этот файл XAML представляет главное окно вашего приложения, в котором отображается созданное содержимое страниц. Класс Window определяет свойства окна, такие как заголовок, размер и значок, и обрабатывает события, такие как открытие и закрытие окна.

  4. Измените элемент Window на NavigationWindow, как показано в следующем коде XAML:

    <NavigationWindow x:Class="ExpenseIt.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         ...
    </NavigationWindow>
    

    Это приложение переходит к другому содержимому в зависимости от введенных пользователем данных. Вот почему главное Window необходимо изменить на NavigationWindow. NavigationWindow наследует все свойства Window. Элемент NavigationWindow в файле XAML создает экземпляр класса NavigationWindow. Дополнительные сведения см. в разделе Общие сведения о переходах.

  5. Удалите элементы Grid между тегамиNavigationWindow.

  6. Измените следующие свойства в коде XAML для элемента NavigationWindow:

    • Задайте свойству Title значение «ExpenseIt».

    • Присвойте свойству Height значение 350 пикселей.

    • Присвойте свойству Width значение 500 пикселей.

    XAML должен выглядеть следующим образом в Visual Basic:

    <NavigationWindow x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ExpenseIt" Height="350" Width="500">
     
    </NavigationWindow>
    

    И как показано ниже - в C#:

    <NavigationWindow x:Class="ExpenseIt.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ExpenseIt" Height="350" Width="500">
        
    </NavigationWindow>
    
  7. Откройте файл MainWindow.xaml.vb или MainWindow.xaml.cs.

    В этом файле кода программной части содержится код обработки событий, объявленных в файле MainWindow.xaml. Этот файл содержит разделяемый класс для окна, определенного в XAML-коде.

  8. Если вы используете C#, измените класс MainWindow на производный от NavigationWindow. (В Visual Basic это выполняется автоматически при изменении окна в XAML-коде.) После этого код C# должен выглядеть таким образом:

    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace ExpenseIt
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : NavigationWindow
        {
            public MainWindow()
            {
                InitializeComponent();
            }
        }
    }
    

Добавление файлов в приложение

В этом разделе вы добавите в приложение две страницы и изображение.

  1. Добавьте новую страницу в проект и назовите ее ExpenseItHome.xaml:

    1. В Обозревателе решений щелкните правой кнопкой мыши по узлу проекта ExpenseIt и выберите Добавить>страницу.

    2. В диалоговом окне «Добавление нового элемента» уже выбран шаблон страницы (WPF). Введите имя ExpenseItHome, а затем нажмите кнопку «Добавить».

    Эта страница отображается первой при запуске приложения. На ней выводится список, в котором можно выбрать человека и просмотреть отчет о его затратах.

  2. Открыть ExpenseItHome.xaml.

  3. Присвойте свойству Title значение «ExpenseIt - Home».

  4. Задайте значение 350 пикселей для DesignHeight и значение 500 пикселей для DesignWidth.

    Теперь XAML отображается следующим образом для Visual Basic:

    <Page x:Class="ExpenseItHome"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="350" d:DesignWidth="500"
      Title="ExpenseIt - Home">
        <Grid>
            
        </Grid>
    </Page>
    

    И как показано ниже - в C#:

    <Page x:Class="ExpenseIt.ExpenseItHome"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
          mc:Ignorable="d" 
          d:DesignHeight="350" d:DesignWidth="500"
        Title="ExpenseIt - Home">
    
        <Grid>
            
        </Grid>
    </Page>
    
  5. Откройте файл MainWindow.xaml.

  6. Добавьте свойство Source в элемент NavigationWindow и присвойте ему значение "ExpenseItHome.xaml".

    Таким образом, ExpenseItHome.xaml устанавливается в качестве первой страницы, открываемой при запуске приложения.

    Пример XAML в Visual Basic:

    <NavigationWindow x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ExpenseIt" Height="350" Width="500" Source="ExpenseItHome.xaml">
        
    </NavigationWindow>
    

    И в C#:

    <NavigationWindow x:Class="ExpenseIt.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ExpenseIt" Height="350" Width="500" Source="ExpenseItHome.xaml">
        
    </NavigationWindow>
    

    Совет

    Вы также можете задать свойство «Источник» в категории «Прочие» окна «Свойства».

    Source property in Properties window

  7. Добавьте в проект еще одну новую страницу WPF и назовите ее ExpenseReportPage.xaml:

    1. В Обозревателе решений щелкните правой кнопкой мыши по узлу проекта ExpenseIt и выберите Добавить>страницу.

    2. В диалоговом окне «Добавление нового элемента» выберите шаблон страницы (WPF). Введите имя ExpenseReportPage и нажмите кнопку «Добавить».

    На этой странице будет выводиться отчет по расходам для человека, выбранного на странице ExpenseItHome.

  8. Откройте файл ExpenseReportPage.xaml.

  9. Присвойте свойству Title значение «ExpenseIt - View Expense».

  10. Задайте значение 350 пикселей для DesignHeight и значение 500 пикселей для DesignWidth.

    Файл ExpenseReportPage.xaml теперь выглядит следующим образом в Visual Basic:

    <Page x:Class="ExpenseReportPage"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
          mc:Ignorable="d" 
          d:DesignHeight="350" d:DesignWidth="500"
          Title="ExpenseIt - View Expense">
        <Grid>
            
        </Grid>
    </Page>
    

    И как показано ниже - в C#:

    <Page x:Class="ExpenseIt.ExpenseReportPage"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
          mc:Ignorable="d" 
          d:DesignHeight="350" d:DesignWidth="500"
        Title="ExpenseIt - View Expense">
    
        <Grid>
            
        </Grid>
    </Page>
    
  11. Откройте файлы ExpenseItHome.xaml.vb и ExpenseReportPage.xaml.vb или ExpenseItHome.xaml.cs и ExpenseReportPage.xaml.cs.

    При создании нового файла страницы Visual Studio автоматически создает файл его кода программной части. Эти файлы кода программной части обрабатывают логику, реагирующую на действия пользователя.

    Код должен выглядеть так, как показано ниже, для ExpenseItHome:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace ExpenseIt
    {
        /// <summary>
        /// Interaction logic for ExpenseItHome.xaml
        /// </summary>
        public partial class ExpenseItHome : Page
        {
            public ExpenseItHome()
            {
                InitializeComponent();
            }
        }
    }
    
    Class ExpenseItHome
    
    End Class
    

    И как показано ниже - для ExpenseReportPage:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace ExpenseIt
    {
        /// <summary>
        /// Interaction logic for ExpenseReportPage.xaml
        /// </summary>
        public partial class ExpenseReportPage : Page
        {
            public ExpenseReportPage()
            {
                InitializeComponent();
            }
        }
    }
    
    Class ExpenseReportPage
    
    End Class
    
  12. Добавьте в проект изображение с именем watermark.png. Вы можете создать собственное изображение, скопировать файл из примера кода или получить его из репозитория GitHub microsoft/WPF-Samples.

    1. Щелкните правой кнопкой мыши по узлу проекта и выберите командуДобавить>существующий элемент или нажмите клавишиShift+Alt+A.

    2. В диалоговом окне "Добавление существующего элемента" установите фильтр файлов "Все файлы" или "Файлы изображений", перейдите к файлу изображения, который вы хотите использовать, и нажмите кнопку "Добавить".

    3. Выберите файл изображения в Обозревателе решений, а затем в окне "Свойства" задайте для параметра "Действие сборки" значение "Ресурс".

Создание и запуск приложения

  1. Выполните сборку и запуск приложения, воспользовавшись клавишей F5 или выбрав пункт Начать отладку в меню Отладка.

    На рисунке ниже показано приложение с кнопками NavigationWindow:

    Application after you build and run it.

  2. Закройте приложение, чтобы вернуться в Visual Studio.

Создание макета

Макет позволяет упорядочивать размещение элементов пользовательского интерфейса, а также управлять их размером и положением при изменении размеров пользовательского интерфейса. Обычно макет создается с одним из следующих элементов управления макетом.

  • Canvas - Определяет область, внутри которой можно явным образом разместить дочерние элементы с помощью координат, относящихся к области холста.
  • DockPanel - Определяет область, в которой можно упорядочивать дочерние элементы горизонтально либо вертикально относительно друг друга.
  • Grid - Задание области с таблицей переменного размера, состоящей из столбцов и строк.
  • StackPanel - Выравнивает дочерние элементы в одну линию, ориентированную горизонтально или вертикально.
  • VirtualizingStackPanel - Упорядочивает и виртуализирует одну строку содержимого, ориентированную горизонтально или вертикально.
  • WrapPanel - Размещает дочерние элементы последовательно слева направо, перенося содержимое на следующую строку на краю содержащего поля. Последующее размещение происходит последовательно сверху вниз или справа налево, в зависимости от значения свойства «Ориентация».

Каждый из этих элементов управления макетом поддерживает специальный тип макета дочерних элементов. Размер страниц приложения ExpenseIt может быть изменен. На каждой странице представлены элементы, которые упорядочены по горизонтали и вертикали рядом с другими элементами. В этом примере Grid используется в качестве элемента макета для приложения.

Совет

Дополнительные сведения об элементах Panel см. в разделе Общие сведения о панелях. Дополнительные сведения о макете см. в разделе Макет.

В этом разделе создается таблица с одним столбцом, тремя строками и полями шириной 10 пикселей путем добавления определений столбцов и строк в класс Grid в файле ExpenseItHome.xaml.

  1. В ExpenseItHome.xaml задайте свойству Margin в элементе Grid значение "10,0,10,10", что соответствует левому, верхнему, правому и нижнему полям:

    <Grid Margin="10,0,10,10">
    

    Совет

    Значения полей также можно задать в окне «Свойства» в категории «Макет» :

    Margin values in Properties window

  2. Добавьте следующий код XAML между тегами Grid, чтобы создать определения строк и столбцов:

    <Grid.ColumnDefinitions>
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition />
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    

    Для Height двух строк задано значение Auto, что означает, что размер строк определяется содержимым строк. Для Height по умолчанию задано определение размера Star, что означает, что высота строки представляет собой взвешенную пропорцию доступного пространства. Например, если каждая из двух строк имеет Height "*", высота каждой из них будет равна половине имеющегося свободного места.

    Теперь Grid должен содержать следующий код XAML:

    <Grid Margin="10,0,10,10">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition />
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
    </Grid>
    

Добавление элементов управления

В этом разделе вы научитесь обновлять пользовательский интерфейс домашней страницы, чтобы отображать список людей, в которых вы выберете одного человека для отображения его отчета о расходах. Элементы управления — это объекты пользовательского интерфейса, позволяющие пользователям взаимодействовать с приложением. Более подробную информацию см. в разделе Элементы управления.

Чтобы создать этот пользовательский интерфейс, добавьте следующие элементы ExpenseItHome.xaml:

  • ListBox (для списка людей).
  • Label (для заголовка списка).
  • Button (кнопка для просмотра отчета о расходах для выбранного в списке человека).

Каждый элемент управления размещается в строке Grid путем задания значения присоединенному свойству Grid.Row. Дополнительные сведения о присоединенных свойствах см. в разделах Общие сведения о присоединенных свойствах.

  1. Добавьте ExpenseItHome.xamlследующий XAML-код между тегами Grid:

    
    <!-- People list -->
    <Border Grid.Column="0" Grid.Row="0" Height="35" Padding="5" Background="#4E87D4">
        <Label VerticalAlignment="Center" Foreground="White">Names</Label>
    </Border>
    <ListBox Name="peopleListBox" Grid.Column="0" Grid.Row="1">
        <ListBoxItem>Mike</ListBoxItem>
        <ListBoxItem>Lisa</ListBoxItem>
        <ListBoxItem>John</ListBoxItem>
        <ListBoxItem>Mary</ListBoxItem>
    </ListBox>
    
    <!-- View report button -->
    <Button Grid.Column="0" Grid.Row="2" Margin="0,10,0,10" Width="125" Height="25" HorizontalAlignment="Right">View</Button>
    

    Совет

    Элементы управления можно также создать, перетащив их из окна Панель инструментов в окно разработки и задав их свойства в окне Свойства.

  2. Выполните сборку приложения и запустите его.

    На следующем рисунке показаны созданные вами элементы управления:

ExpenseIt sample screenshot displaying a list of names

Добавление изображения и заголовка

В этом разделе вы посмотрите, как обновить пользовательский интерфейс домашней станицы с помощью добавления изображения и заголовка страницы.

  1. Добавьте ExpenseItHome.xamlеще один столбец в ColumnDefinitions с фиксированным значением Width в 230 пикселей:

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="230" />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    
  2. Добавьте в RowDefinitions еще одну строку, чтобы в общей сложности было четыре строки:

    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition Height="Auto"/>
        <RowDefinition />
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    
  3. Переместите элементы управления во второй столбец, задав для свойства Grid.Column значение 1 в каждом из трех элементов управления (Border, ListBox и Button).

  4. Переместит каждый элемент управления вниз по строке путем увеличения его значения Grid.Row на 1 для каждого из трех элементов управления (Border, ListBox и Button) и элемента Border.

    XAML для этих трех элементов управления теперь выглядит следующим образом:

      <Border Grid.Column="1" Grid.Row="1" Height="35" Padding="5" Background="#4E87D4">
          <Label VerticalAlignment="Center" Foreground="White">Names</Label>
      </Border>
      <ListBox Name="peopleListBox" Grid.Column="1" Grid.Row="2">
          <ListBoxItem>Mike</ListBoxItem>
          <ListBoxItem>Lisa</ListBoxItem>
          <ListBoxItem>John</ListBoxItem>
          <ListBoxItem>Mary</ListBoxItem>
      </ListBox>
    
      <!-- View report button -->
      <Button Grid.Column="1" Grid.Row="3" Margin="0,10,0,0" Width="125"
    Height="25" HorizontalAlignment="Right">View</Button>
    
  5. Задайте для свойства Фон файл изображения watermark.png, добавив следующий код XAML в любом месте между тегами <Grid> и </Grid>:

    <Grid.Background>
        <ImageBrush ImageSource="watermark.png"/>
    </Grid.Background>
    
  6. Перед элементом Border добавьте Label с содержимым "Просмотреть отчет о расходах". Эта метка является заголовком страницы.

    <Label Grid.Column="1" VerticalAlignment="Center" FontFamily="Trebuchet MS" 
            FontWeight="Bold" FontSize="18" Foreground="#0066cc">
        View Expense Report
    </Label>
    
  7. Выполните сборку приложения и запустите его.

На следующем рисунке показаны результаты только что добавленных элементов:

ExpenseIt sample screenshot showing the new image background and page title

Добавление кода для обработки событий

  1. В ExpenseItHome.xaml добавьте обработчик событий Click в элемент Button. Дополнительные сведения см. в разделе Практическое руководство: Создание простого обработчика событий.

      <!-- View report button -->
      <Button Grid.Column="1" Grid.Row="3" Margin="0,10,0,0" Width="125"
    Height="25" HorizontalAlignment="Right" Click="Button_Click">View</Button>
    
  2. Откройте ExpenseItHome.xaml.vb или ExpenseItHome.xaml.cs.

  3. Добавьте следующий код в класс ExpenseItHome, чтобы добавить обработчик событий нажатия кнопки. Обработчик событий открывает страницу ExpenseReportPage.

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        // View Expense Report
        ExpenseReportPage expenseReportPage = new ExpenseReportPage();
        this.NavigationService.Navigate(expenseReportPage);
    }
    
    Private Sub Button_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        ' View Expense Report
        Dim expenseReportPage As New ExpenseReportPage()
        Me.NavigationService.Navigate(expenseReportPage)
    
    End Sub
    

Создание пользовательского интерфейса для страницы ExpenseReportPage

На странице ExpenseReportPage.xaml отображается отчет о расходах для человека, выбранного на странице ExpenseItHome. В этом разделе вы создадите пользовательский интерфейс для ExpenseReportPage. Вы также научитесь добавлять фон и цвета заливки для различных элементов.

  1. Откройте файл ExpenseReportPage.xaml.

  2. Добавьте следующий XAML-код между тегами Grid:

     <Grid.Background>
         <ImageBrush ImageSource="watermark.png" />
     </Grid.Background>
     <Grid.ColumnDefinitions>
         <ColumnDefinition Width="230" />
         <ColumnDefinition />
     </Grid.ColumnDefinitions>
     <Grid.RowDefinitions>
         <RowDefinition Height="Auto" />
         <RowDefinition />
     </Grid.RowDefinitions>
    
    
     <Label Grid.Column="1" VerticalAlignment="Center" FontFamily="Trebuchet MS" 
     FontWeight="Bold" FontSize="18" Foreground="#0066cc">
         Expense Report For:
     </Label>
     <Grid Margin="10" Grid.Column="1" Grid.Row="1">
    
         <Grid.ColumnDefinitions>
             <ColumnDefinition />
             <ColumnDefinition />
         </Grid.ColumnDefinitions>
         <Grid.RowDefinitions>
             <RowDefinition Height="Auto" />
             <RowDefinition Height="Auto" />
             <RowDefinition />
         </Grid.RowDefinitions>
    
         <!-- Name -->
         <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" Orientation="Horizontal">
             <Label Margin="0,0,0,5" FontWeight="Bold">Name:</Label>
             <Label Margin="0,0,0,5" FontWeight="Bold"></Label>
         </StackPanel>
    
         <!-- Department -->
         <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" Orientation="Horizontal">
             <Label Margin="0,0,0,5" FontWeight="Bold">Department:</Label>
             <Label Margin="0,0,0,5" FontWeight="Bold"></Label>
         </StackPanel>
    
         <Grid Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="2" VerticalAlignment="Top" 
               HorizontalAlignment="Left">
             <!-- Expense type and Amount table -->
             <DataGrid  AutoGenerateColumns="False" RowHeaderWidth="0" >
                 <DataGrid.ColumnHeaderStyle>
                     <Style TargetType="{x:Type DataGridColumnHeader}">
                         <Setter Property="Height" Value="35" />
                         <Setter Property="Padding" Value="5" />
                         <Setter Property="Background" Value="#4E87D4" />
                         <Setter Property="Foreground" Value="White" />
                     </Style>
                 </DataGrid.ColumnHeaderStyle>
                 <DataGrid.Columns>
                     <DataGridTextColumn Header="ExpenseType" />
                     <DataGridTextColumn Header="Amount"  />
                 </DataGrid.Columns>
             </DataGrid>
         </Grid>
     </Grid>
    

    Этот пользовательский интерфейс аналогичен ExpenseItHome.xaml, за исключением того, что отчетные данные отображаются в DataGrid.

  3. Выполните сборку приложения и запустите его.

  4. Нажмите кнопку Просмотр.

    Появится страница отчета по расходам. Обратите внимание на то, что кнопка возврата активна.

На следующем рисунке показаны элементы пользовательского интерфейса, добавленные на страницу ExpenseReportPage.xaml.

ExpenseIt sample screenshot showing the UI just created for the ExpenseReportPage.

Элементы управления стилем

Внешний вид различных элементов часто одинаковый для всех элементов пользовательского интерфейса одного типа. Пользовательский интерфейс использует стили, чтобы варианты внешнего вида можно было многократно использовать для нескольких элементов. Повторное использование стилей помогает упростить создание кода XAML и управление им. В этом разделе атрибуты, установленные ранее для каждого элемента, заменяются стилями.

  1. Откройте файл Application.xaml или App.xaml.

  2. Добавьте следующий XAML-код между тегами Application.Resources:

    
    <!-- Header text style -->
    <Style x:Key="headerTextStyle">
        <Setter Property="Label.VerticalAlignment" Value="Center"></Setter>
        <Setter Property="Label.FontFamily" Value="Trebuchet MS"></Setter>
        <Setter Property="Label.FontWeight" Value="Bold"></Setter>
        <Setter Property="Label.FontSize" Value="18"></Setter>
        <Setter Property="Label.Foreground" Value="#0066cc"></Setter>
    </Style>
    
    <!-- Label style -->
    <Style x:Key="labelStyle" TargetType="{x:Type Label}">
        <Setter Property="VerticalAlignment" Value="Top" />
        <Setter Property="HorizontalAlignment" Value="Left" />
        <Setter Property="FontWeight" Value="Bold" />
        <Setter Property="Margin" Value="0,0,0,5" />
    </Style>
    
    <!-- DataGrid header style -->
    <Style x:Key="columnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}">
        <Setter Property="Height" Value="35" />
        <Setter Property="Padding" Value="5" />
        <Setter Property="Background" Value="#4E87D4" />
        <Setter Property="Foreground" Value="White" />
    </Style>
    
    <!-- List header style -->
    <Style x:Key="listHeaderStyle" TargetType="{x:Type Border}">
        <Setter Property="Height" Value="35" />
        <Setter Property="Padding" Value="5" />
        <Setter Property="Background" Value="#4E87D4" />
    </Style>
    
    <!-- List header text style -->
    <Style x:Key="listHeaderTextStyle" TargetType="{x:Type Label}">
        <Setter Property="Foreground" Value="White" />
        <Setter Property="VerticalAlignment" Value="Center" />
        <Setter Property="HorizontalAlignment" Value="Left" />
    </Style>
    
    <!-- Button style -->
    <Style x:Key="buttonStyle" TargetType="{x:Type Button}">
        <Setter Property="Width" Value="125" />
        <Setter Property="Height" Value="25" />
        <Setter Property="Margin" Value="0,10,0,0" />
        <Setter Property="HorizontalAlignment" Value="Right" />
    </Style>
    

    Этот код XAML добавляет следующие стили:

    • headerTextStyleдля форматирования заголовка страницы Label;

    • labelStyleдля форматирования элементов управления Label ;

    • columnHeaderStyleдля форматирования DataGridColumnHeader;

    • listHeaderStyleдля форматирования элементов управления Border заголовков списка;

    • listHeaderTextStyle: Для форматирования заголовка списка Label.

    • buttonStyle: Для форматирования Button в ExpenseItHome.xaml.

    Обратите внимание, что стили являются ресурсами и дочерними элементами элемента свойства Application.Resources. Здесь стили применяются ко всем элементам в приложении. Пример использования ресурсов в приложении .NET см. в разделе Использование ресурсов приложения.

  3. В ExpenseItHome.xaml замените весь код между элементами Grid на приведенный ниже код XAML:

       <Grid.Background>
           <ImageBrush ImageSource="watermark.png"  />
       </Grid.Background>
      
       <Grid.ColumnDefinitions>
           <ColumnDefinition Width="230" />
           <ColumnDefinition />
       </Grid.ColumnDefinitions>
       
       <Grid.RowDefinitions>
           <RowDefinition/>
           <RowDefinition Height="Auto"/>
           <RowDefinition />
           <RowDefinition Height="Auto"/>
       </Grid.RowDefinitions>
    
       <!-- People list -->
      
       <Label Grid.Column="1" Style="{StaticResource headerTextStyle}" >
           View Expense Report
       </Label>
       
       <Border Grid.Column="1" Grid.Row="1" Style="{StaticResource listHeaderStyle}">
           <Label Style="{StaticResource listHeaderTextStyle}">Names</Label>
       </Border>
       <ListBox Name="peopleListBox" Grid.Column="1" Grid.Row="2">
           <ListBoxItem>Mike</ListBoxItem>
           <ListBoxItem>Lisa</ListBoxItem>
           <ListBoxItem>John</ListBoxItem>
           <ListBoxItem>Mary</ListBoxItem>
       </ListBox>
    
       <!-- View report button -->
       <Button Grid.Column="1" Grid.Row="3" Click="Button_Click" Style="{StaticResource buttonStyle}">View</Button>
    

    Свойства, определяющие внешний вид элементов управления, такие как VerticalAlignment и FontFamily , при применении стилей удаляются и заменяются. Например, headerTextStyle применяется к тексту «View Expense Report» Label.

  4. Откройте файл ExpenseReportPage.xaml.

  5. Замените весь код между элементами Grid на приведенный ниже код XAML:

      <Grid.Background>
          <ImageBrush ImageSource="watermark.png" />
      </Grid.Background>
      <Grid.ColumnDefinitions>
          <ColumnDefinition Width="230" />
          <ColumnDefinition />
      </Grid.ColumnDefinitions>
      <Grid.RowDefinitions>
          <RowDefinition Height="Auto" />
          <RowDefinition />
      </Grid.RowDefinitions>
    
    
      <Label Grid.Column="1" Style="{StaticResource headerTextStyle}">
          Expense Report For:
      </Label>
      <Grid Margin="10" Grid.Column="1" Grid.Row="1">
    
          <Grid.ColumnDefinitions>
              <ColumnDefinition />
              <ColumnDefinition />
          </Grid.ColumnDefinitions>
          <Grid.RowDefinitions>
              <RowDefinition Height="Auto" />
              <RowDefinition Height="Auto" />
              <RowDefinition />
          </Grid.RowDefinitions>
    
          <!-- Name -->
          <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" Orientation="Horizontal">
              <Label Style="{StaticResource labelStyle}">Name:</Label>
              <Label Style="{StaticResource labelStyle}"></Label>
          </StackPanel>
    
          <!-- Department -->
          <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" 
      Orientation="Horizontal">
              <Label Style="{StaticResource labelStyle}">Department:</Label>
              <Label Style="{StaticResource labelStyle}"></Label>
          </StackPanel>
    
          <Grid Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="2" VerticalAlignment="Top" 
                HorizontalAlignment="Left">
              <!-- Expense type and Amount table -->
              <DataGrid ColumnHeaderStyle="{StaticResource columnHeaderStyle}" 
                        AutoGenerateColumns="False" RowHeaderWidth="0" >
                  <DataGrid.Columns>
                      <DataGridTextColumn Header="ExpenseType" />
                      <DataGridTextColumn Header="Amount"  />
                  </DataGrid.Columns>
              </DataGrid>
          </Grid>
      </Grid>
    

    Этот код XAML добавляет стили в элементы Label и Border.

  6. Выполните сборку приложения и запустите его. Внешний вид окна совпадает с предыдущим внешним видом.

    ExpenseIt sample screenshot with the same appearance as in the last section.

  7. Закройте приложение, чтобы вернуться в Visual Studio.

Привязка данных к элементу управления

В этом разделе вы научитесь создавать данные XML, привязанные к различным элементам управления.

  1. В ExpenseItHome.xaml, после открытия элемента Grid, добавьте следующий XAML-код для создания XmlDataProvider, содержащего данные по каждому человеку:

    <Grid.Resources>
        <!-- Expense Report Data -->
        <XmlDataProvider x:Key="ExpenseDataSource" XPath="Expenses">
            <x:XData>
                <Expenses xmlns="">
                    <Person Name="Mike" Department="Legal">
                        <Expense ExpenseType="Lunch" ExpenseAmount="50" />
                        <Expense ExpenseType="Transportation" ExpenseAmount="50" />
                    </Person>
                    <Person Name="Lisa" Department="Marketing">
                        <Expense ExpenseType="Document printing"
              ExpenseAmount="50"/>
                        <Expense ExpenseType="Gift" ExpenseAmount="125" />
                    </Person>
                    <Person Name="John" Department="Engineering">
                        <Expense ExpenseType="Magazine subscription" 
             ExpenseAmount="50"/>
                        <Expense ExpenseType="New machine" ExpenseAmount="600" />
                        <Expense ExpenseType="Software" ExpenseAmount="500" />
                    </Person>
                    <Person Name="Mary" Department="Finance">
                        <Expense ExpenseType="Dinner" ExpenseAmount="100" />
                    </Person>
                </Expenses>
            </x:XData>
        </XmlDataProvider>
    </Grid.Resources>
    

    Данные создаются как ресурс Grid. Обычно такие данные загружаются в виде файла, но для простоты в этом примере они добавляются в коде.

  2. В элементе <Grid.Resources> добавьте следующий элемент <xref:System.Windows.DataTemplate>, который определяет способ отображения данных в элементе ListBox после элемента <XmlDataProvider>:

    <Grid.Resources>
        <!-- Name item template -->
        <DataTemplate x:Key="nameItemTemplate">
            <Label Content="{Binding XPath=@Name}"/>
        </DataTemplate>
    </Grid.Resources>
    

    Дополнительные сведения о шаблонах данных см. в разделе Общие сведения о шаблонах данных.

  3. Замените существующий ListBox следующим кодом XAML:

    <ListBox Name="peopleListBox" Grid.Column="1" Grid.Row="2" 
             ItemsSource="{Binding Source={StaticResource ExpenseDataSource}, XPath=Person}"
             ItemTemplate="{StaticResource nameItemTemplate}">
    </ListBox>
    

    Этот код XAML привязывает свойство ItemsSource элемента ListBox к источнику данных, а затем применяет шаблон данных как ItemTemplate.

Подключение данных к элементам управления

Затем добавьте код, чтобы получить имя, выбранное на ExpenseItHome странице, и передать его конструктору страницы ExpenseReportPage. ExpenseReportPage задает контекст данных для переданного элемента, к которому будут привязаны элементы управления, определенные в файле ExpenseReportPage.xaml.

  1. Откройте файл ExpenseReportPage.xaml.vb или ExpenseReportPage.xaml.cs.

  2. Добавьте конструктор, принимающий объект, чтобы можно было передавать данные отчета о затратах выбранного человека.

    public partial class ExpenseReportPage : Page
    {
        public ExpenseReportPage()
        {
            InitializeComponent();
        }
    
        // Custom constructor to pass expense report data
        public ExpenseReportPage(object data):this()
        {
            // Bind to expense report data.
            this.DataContext = data;
        }
    }
    
    Partial Public Class ExpenseReportPage
        Inherits Page
        Public Sub New()
            InitializeComponent()
        End Sub
    
        ' Custom constructor to pass expense report data
        Public Sub New(ByVal data As Object)
            Me.New()
            ' Bind to expense report data.
            Me.DataContext = data
        End Sub
    
    End Class
    
  3. Откройте ExpenseItHome.xaml.vb или ExpenseItHome.xaml.cs.

  4. Измените обработчик событий Click так, чтобы он вызывал новый конструктор и передавал ему данные отчета о затратах выбранного человека.

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        // View Expense Report
        ExpenseReportPage expenseReportPage = new ExpenseReportPage(this.peopleListBox.SelectedItem);
        this.NavigationService.Navigate(expenseReportPage);
    }
    
    Private Sub Button_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        ' View Expense Report
        Dim expenseReportPage As New ExpenseReportPage(Me.peopleListBox.SelectedItem)
        Me.NavigationService.Navigate(expenseReportPage)
    
    End Sub
    

Стилизация данных с помощью шаблонов данных

В этом разделе вы научитесь обновлять пользовательский интерфейс каждого элемента в списках с привязкой данных с помощью шаблонов данных.

  1. Откройте файл ExpenseReportPage.xaml.

  2. Привяжите содержимое «Имя» и «Отдел» элементов Labelк соответствующему свойству источника данных. Дополнительные сведения о привязке данных см. в разделе Общие сведения о привязке данных.

    <!-- Name -->
    <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" Orientation="Horizontal">
        <Label Style="{StaticResource labelStyle}">Name:</Label>
        <Label Style="{StaticResource labelStyle}" Content="{Binding XPath=@Name}"></Label>
    </StackPanel>
    
    <!-- Department -->
    <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" Orientation="Horizontal">
        <Label Style="{StaticResource labelStyle}">Department:</Label>
        <Label Style="{StaticResource labelStyle}" Content="{Binding XPath=@Department}"></Label>
    </StackPanel>
    
  3. Открыв элемент Grid, добавьте следующие шаблоны данных, определяющие способ отображения отчета о затратах:

    <!--Templates to display expense report data-->
    <Grid.Resources>
        <!-- Reason item template -->
        <DataTemplate x:Key="typeItemTemplate">
            <Label Content="{Binding XPath=@ExpenseType}"/>
        </DataTemplate>
        <!-- Amount item template -->
        <DataTemplate x:Key="amountItemTemplate">
            <Label Content="{Binding XPath=@ExpenseAmount}"/>
        </DataTemplate>
    </Grid.Resources>
    
  4. Замените элементы DataGridTextColumn на DataGridTemplateColumn под элементом DataGrid и примените к ним шаблоны. Кроме того, укажите атрибут ItemsSource со значением в элементе DataGrid.

    <!-- Expense type and Amount table -->
    <DataGrid ItemsSource="{Binding XPath=Expense}" ColumnHeaderStyle="{StaticResource columnHeaderStyle}" AutoGenerateColumns="False" RowHeaderWidth="0" >
       
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="ExpenseType" CellTemplate="{StaticResource typeItemTemplate}" />
            <DataGridTemplateColumn Header="Amount" CellTemplate="{StaticResource amountItemTemplate}" />
        </DataGrid.Columns>
        
    </DataGrid>
    
  5. Выполните сборку приложения и запустите его.

  6. Выберите человека и нажмите кнопку Просмотреть.

На рисунке ниже показаны обе страницы приложения ExpenseIt с элементами управления, макетом, стилями, привязкой данных и примененными шаблонами данных:

Both pages of the app showing the names list and an expense report.

Примечание.

В этом примере демонстрируется определенная функция WPF и не выполняются все рекомендации по обеспечению безопасности, локализации и доступности. Подробные рекомендации по разработке приложений для WPF и .NET с учетом всех рекомендаций см. в следующих разделах:

Следующие шаги

В этом пошаговом руководстве вы узнали о нескольких методах создания пользовательского интерфейса с помощью Windows Presentation Foundation (WPF). Вы получили общее представление о составных элементах приложения .NET с привязкой данных. Более подробную информацию об архитектуре и моделях программирования WPF см. в следующих разделах:

Более подробную информацию о создании приложений см. в следующих разделах:

См. также