Если вы пропустили предыдущие четыре части, вы можете легко найти их здесь:
- Создание клиента Imgur для Windows Phone — часть 1 — Core & Main Gallery
- Создание клиента Imgur для Windows Phone — часть 2 — бесконечная прокрутка изображений
- Создание клиента Imgur для Windows Phone — часть 3 — просмотр сведений об изображении
- Создание клиента Imgur для Windows Phone — Часть 4 — Аутентификация
В предыдущей статье я говорил о создании механизма загрузки. Теперь я собираюсь поговорить о создании рабочего процесса пользовательского интерфейса, необходимого для создания удобной процедуры загрузки.
Я создаю новую страницу загрузки ( UploadPage.xaml ), которая позволяет пользователю выбрать изображение из библиотеки мультимедиа, а также при необходимости создать новую. Не только это, но я также даю пользователю возможность ввести название и описание изображения, даже если они не являются обязательными.
Полный XAML выглядит так:
<phone:PhoneApplicationPage x:Class="Imagine.UploadPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" mc:Ignorable="d" xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit" shell:SystemTray.IsVisible="False"> <!--LayoutRoot is the root grid where all page content is placed--> <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--TitlePanel contains the name of the application and page title--> <StackPanel Grid.Row="0" Margin="12,17,0,28"> <TextBlock Text="UPLOAD IMAGE" Style="{StaticResource PhoneTextNormalStyle}"/> </StackPanel> <!--ContentPanel - place additional content here--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <Grid.RowDefinitions> <RowDefinition Height="230"></RowDefinition> <RowDefinition Height="*"></RowDefinition> </Grid.RowDefinitions> <Image Stretch="UniformToFill" x:Name="imgPreview" Margin="12,12,12,12"></Image> <Button x:Name="btnPick" Click="btnPick_Click_1"> <Image Source="/Images/photocapture.png"></Image> </Button> <StackPanel Grid.Row="1"> <TextBlock Style="{StaticResource PhoneTextTitle3Style}">Name:</TextBlock> <TextBox x:Name="txtName"></TextBox> <TextBlock Style="{StaticResource PhoneTextTitle3Style}">Description:</TextBlock> <TextBox x:Name="txtDescription" TextWrapping="Wrap" AcceptsReturn="True" TextOptions.TextHintingMode="Animated" Height="210"></TextBox> </StackPanel> </Grid> <Grid Visibility="Collapsed" Grid.RowSpan="2" x:Name="grdUploading"> <Grid.Background> <SolidColorBrush Color="Black"></SolidColorBrush> </Grid.Background> <TextBlock Text="Uploading..." HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock> <toolkit:PerformanceProgressBar IsIndeterminate="True" Margin="0,80,0,0"></toolkit:PerformanceProgressBar> </Grid> </Grid> <phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar> <shell:ApplicationBarIconButton x:Name="btnUpload" Click="btnUpload_Click_1" Text="ok" IconUri="/Images/appbar.check.png"></shell:ApplicationBarIconButton> <shell:ApplicationBarIconButton x:Name="btnCancel" Click="btnCancel_Click_1" Text="cancel" IconUri="/Images/appbar.cancel.png"></shell:ApplicationBarIconButton> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar> </phone:PhoneApplicationPage>
Чтобы сделать краткий обзор, вот как это выглядит в результате:
Основная рабочая сетка разделена на две части — компонент предварительного просмотра изображения, поверх которого расположен элемент управления Button , и мета-область, предназначенная для указания имени и описания загружаемого изображения.
Элемент управления изображением за кнопкой будет отображать выбранный контент. В то же время основной фон сетки (для LayoutRoot ) также будет отображать выбранное изображение, хотя и в гораздо большем формате. Все это делается с помощью PhotoChooserTask :
PhotoChooserTask task = new PhotoChooserTask() { ShowCamera = true }; task.Completed += (s, d) => { if (d.TaskResult == TaskResult.OK) { byte[] buffer = new byte[16 * 1024]; using (MemoryStream stream = new MemoryStream()) { int read = 0; while ((read = d.ChosenPhoto.Read(buffer, 0, buffer.Length)) > 0) { stream.Write(buffer, 0, read); } BitmapImage image = new BitmapImage(); image.SetSource(stream); imgPreview.Source = image; ImageBrush brush = new ImageBrush(); brush.ImageSource = image; LayoutRoot.Background = brush; brush.Opacity = .2; brush.Stretch = Stretch.UniformToFill; ImageContent = stream.ToArray(); } } }; task.Show();
ImageContent — это общий байтовый буфер, который будет использоваться, если пользователь хочет загрузить выбранное изображение. Как только выбор сделан, пользовательский интерфейс будет выглядеть так:
Вот фрагмент кода, который активирует загрузку:
grdUploading.Visibility = System.Windows.Visibility.Visible; this.ApplicationBar.IsVisible = false; App.ServiceClient.UploadImage(ImageContent, txtName.Text, txtDescription.Text, (n, image) => { if (n) { Dispatcher.BeginInvoke(() => { Clipboard.SetText(image.Image.Link); MessageBox.Show("Your image was uploaded. The link is placed in the clipboard.", "Image Upload", MessageBoxButton.OK); if (NavigationService.CanGoBack) NavigationService.GoBack(); }); } else { Dispatcher.BeginInvoke(() => { MessageBox.Show("There was an error uploading the image. Please try again later.", "Image Upload", MessageBoxButton.OK); }); } Dispatcher.BeginInvoke(() => { grdUploading.Visibility = System.Windows.Visibility.Collapsed; this.ApplicationBar.IsVisible = true; }); });
Когда пользователи принимают изображение, наложение блокирует весь пользовательский интерфейс, чтобы показать, что идет загрузка:
Настраиваемое действие, которое передается в UploadImage, будет вызвано двумя аргументами — логическим флагом, показывающим, была ли загрузка успешной или нет, и десериализованным экземпляром ImgurAtomicImageData . Если первый аргумент равен true, тогда я устанавливаю URL изображения в буфер обмена, чтобы пользователь мог поделиться им при необходимости. Если загрузка не удалась, пользователю сообщают об этом.
Вы можете скачать текущий исходный код проекта здесь . Не забудьте указать свой ключ API и секрет.