Задание: продолжая проект, полученный в результате выполнения первого практического задания, измените внешний вид приложения в соответствии со спецификой выбранной темы (источников данных) и рекомендациями ниже.
Сейчас ваше приложение проверяет доступ в интернет и при запуске должно выглядеть аналогично следующей картинке.
У нас все выглядит гораздо лучше, чем раньше, но почему все топики отображаются плитками одного размера? Пожалуй, надо сделать, как в Windows Store!
Это несколько более сложная задача, чем все то, что мы делали раньше. Но мы не останавливаемся перед трудностями!
Для того, чтобы реализовать подобный функционал, нам придется создать свой класс, наследник GridView. Добавьте в проект новый файл класса с именем: VariableSizeGridView.cs. В новом файле, добавьте в блок using директиву:
using Windows.UI.Xaml.Controls;
укажите, что класс наследуется от GridView и переопределите в нем метод класса: PrepareContainerForItemOverride. В результате должно получиться что-то вроде этого:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml.Controls;
namespace MyReader
{
class VariableSizeGridView: GridView
{
protected override void PrepareContainerForItemOverride
(Windows.UI.Xaml.DependencyObject element, object item)
{
base.PrepareContainerForItemOverride(element, item);
}
}
}
Собственно метод PrepareContainerForItemOverride и будет определять логику, по которой будут отображаться плитки разного размера в сгруппированном представлении. Теперь необходимо подготовить разметку в файле GroupedItemsPage.xaml.
Сначала заменяем GridView на наш класс — local:VariableSizeGridView. Далее в ItemsPanelTemplate дополняем свойства VariableSizedWrapGrid указав размер Item-а и максимальное количество строк и колонок, так, что он будет выглядеть следующим образом:
<VariableSizedWrapGrid Orientation="Vertical" Margin="0,0,80,0" ItemWidth="200" ItemHeight="125" MaximumRowsOrColumns="9" />
Добавим собственный шаблон Item в ресурсы страницы:
<DataTemplate x:Key="CustomItemTemplate">
<Grid HorizontalAlignment="Left">
<Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
<Image Source="{Binding Image}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
</Border>
<StackPanel Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}" VerticalAlignment="Bottom">
<TextBlock Text="{Binding Title}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}"
Height="90" Margin="15,0,15,0" FontSize="30" />
</StackPanel>
</Grid>
</DataTemplate>
И укажем его в качестве шаблона Item, вместо стандартного в local:VariableSizeGridView::
<local:VariableSizeGridView
x:Name="itemGridView"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Grouped Items"
Grid.RowSpan="2"
Padding="116,137,40,46"
ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}"
ItemTemplate="{StaticResource CustomItemTemplate}"
SelectionMode="None"
IsSwipeEnabled="false"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick">
Запускаем приложение.
Выглядит не очень красиво. Но это пока мы не добавим наш код с логикой в PrepareContainerForItemOverride.
Итак, добавляем код:
class VariableSizeGridView: GridView
{
private int rowVal;
private int colVal;
protected override void PrepareContainerForItemOverride(Windows.UI.Xaml.DependencyObject element, object item)
{
RSSDataItem dataItem = item as RSSDataItem;
int index = -1;
if (dataItem != null)
{
index = dataItem.Group.Items.IndexOf(dataItem);
}
if (index == 1)
{
colVal = 2;
rowVal = 4;
}
else
{
colVal = 2;
rowVal = 2;
}
if (index == 2)
{
colVal = 2;
rowVal = 4;
}
if (index == 5)
{
colVal = 4;
rowVal = 4;
}
VariableSizedWrapGrid.SetRowSpan(element as UIElement, rowVal);
VariableSizedWrapGrid.SetColumnSpan(element as UIElement, colVal);
base.PrepareContainerForItemOverride(element, item);
}
Как видно, мы просто руками указываем какую по порядку плитку, как отображать.
Запустим еще раз.
Выглядит гораздо лучше, а реализуя шаблоны для Item и логику работы PrepareContainerForItemOverride можем добиться практически любого представления в пределах GridView.
Теперь у нас красивые плитки разных размеров, причем, мы можем, при желании замостить по разному группы. Давайте это сделаем. Блог Стаса Павлова сделаем с плитками разных размеров, а для Блога Сергея Пугачева – не будем баловать пользователя таким разнообразием.
Как это сделать? Все очень просто. Логика, которая определяет размеры плиток вся реализована в функции PrepareContainerForItemOverride класса VariableSizeGridView, так что можно добавить туда соответствующую логику.
Чтобы отличить группы, будем использовать UniqueID, для группы он соответствует URL на RSS. Добавим следующий код в функцию PrepareContainerForItemOverride:
int group = -1;
if (dataItem.Group.UniqueId.Contains("stas"))
{
group = 1;
}
А теперь изменим поведение функции, в зависимости от того, для какой группы она работает, добавив условие.
if (group > 0)
{
if (index == 2)
{
colVal = 2;
rowVal = 4;
}
if (index == 5)
{
colVal = 4;
rowVal = 4;
}
}
Запустим программу, чтобы проверить, как теперь это работает.
Поставим себе еще более сложную задачу. А что если у нас для отображения необходимо использовать вообще разные шаблоны отображения? Это также решаемая задача. Нам опять придется реализовать свой класс, который будет содержать логику, но теперь он будет уже наследоваться от DataTemplateSelector.
Итак, добавим в решение новый класс с именем MyDataTemplateSelector, указываем, что он наследутся от DataTemplateSelector. Добавяляем в using директивы:
using Windows.UI.Xaml; using Windows.UI.Xaml.Controls;
И переопределяем функцию SelectTemplateCore. В результате должно получится следующее:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace MyReader
{
class MyDataTemplateSelector : DataTemplateSelector
{
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
return base.SelectTemplateCore(item, container);
}
}
}
Теперь нужно определить в XAML файле те шаблоны из которых мы будем выбирать. Для этого открываем GroupedItemsPage.xaml и переходим к ресурсам страницы, где у нас определен шаблон CustomItemTemplate:
<DataTemplate x:Key="CustomItemTemplate">
<Grid HorizontalAlignment="Left">
<Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
<Image Source="{Binding Image}" Stretch="UniformToFill"
AutomationProperties.Name="{Binding Title}"/>
</Border>
<StackPanel Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}"
VerticalAlignment="Bottom">
<TextBlock Text="{Binding Title}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}"
Height="90" Margin="15,0,15,0" FontSize="30" />
</StackPanel>
</Grid>
</DataTemplate>
Определим еще один шаблон с минимальными изменениями – изменим выраванивания:
<DataTemplate x:Key="CustomItemTemplate2">
<Grid HorizontalAlignment="Right">
<Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
<Image Source="{Binding Image}" Stretch="UniformToFill"
AutomationProperties.Name="{Binding Title}"/>
</Border>
<StackPanel Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}" VerticalAlignment="Top">
<TextBlock Text="{Binding Title}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}"
Height="90" Margin="15,0,15,0" FontSize="30" />
</StackPanel>
</Grid>
</DataTemplate>
Вернемся теперь к нашему классу MyDataTemplateSelector и добавим код, который определяет, какой шаблон использовать, в зависимости от того, элемент какой группы отображается:
using MyReader.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace MyReader
{
class MyDataTemplateSelector : DataTemplateSelector
{
public DataTemplate Template1 { get; set; }
public DataTemplate Template2 { get; set; }
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
RSSDataItem dataItem = item as RSSDataItem;
if (dataItem.Group.UniqueId.Contains("stas"))
{
return Template1;
}
else
return Template2;
}
}
}
Возвращаемся к GroupedItemsPage.xaml и переходим к ресурсам страницы, где у нас определены шаблоны и инициализируем наш селектор:
<local:MyDataTemplateSelector x:Key="MyDataSelector"
Template1="{StaticResource CustomItemTemplate}"
Template2="{StaticResource CustomItemTemplate2}"/>
И указываем селектор вместо указания шаблона Item для local:VariableSizeGridView:
<local:VariableSizeGridView
x:Name="itemGridView"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Grouped Items"
Grid.RowSpan="2"
Padding="116,137,40,46"
ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}"
ItemTemplateSelector="{StaticResource MyDataSelector}"
SelectionMode="None"
IsSwipeEnabled="false"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick">
Запускаем приложение, чтобы убедиться, что все работает, как запланировано.
И, давайте, как пример дальнейшей стилизации приложения, изменим стиль текста подписи на плитках группы.
Создадим на основе стиля BasicTextStyle необходимые нам стили и разместим их в ресурсах страницы GroupedItemsPage.xaml:
<Style x:Key="ExtendedTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BasicTextStyle}">
<Setter Property="LineHeight" Value="40"/>
<Setter Property="LineStackingStrategy" Value="BlockLineHeight"/>
<!-- Properly align text along its baseline -->
<Setter Property="RenderTransform">
<Setter.Value>
<TranslateTransform X="-1" Y="4"/>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ExtendedTitleTextStyle" TargetType="TextBlock" BasedOn="{StaticResource ExtendedTextStyle}">
<Setter Property="FontWeight" Value="SemiBold"/>
</Style>
И наложим этот стиль на текст в наших шаблонах::
<DataTemplate x:Key="CustomItemTemplate">
<Grid HorizontalAlignment="Left">
<Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
<Image Source="{Binding Image}" Stretch="UniformToFill"
AutomationProperties.Name="{Binding Title}"/>
</Border>
<StackPanel Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}" VerticalAlignment="Bottom">
<TextBlock Text="{Binding Title}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}"
Style="{StaticResource ExtendedTitleTextStyle}" Height="90" Margin="15,0,15,0" FontSize="30" />
</StackPanel>
</Grid>
</DataTemplate>
<DataTemplate x:Key="CustomItemTemplate2">
<Grid HorizontalAlignment="Right">
<Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
<Image Source="{Binding Image}" Stretch="UniformToFill"
AutomationProperties.Name="{Binding Title}"/>
</Border>
<StackPanel Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}" VerticalAlignment="Top">
<TextBlock Text="{Binding Title}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}"
Style="{StaticResource ExtendedTitleTextStyle}" Height="90" Margin="15,0,15,0" FontSize="30" />
</StackPanel>
</Grid>
</DataTemplate>
Запустим приложение и посмотрим, как теперь выглядят подписи на сгруппированых элементах.
Все выглядит гораздо лучше. Если есть желание, можно поиграться со стилями, добиваясь желаемого эффекта.
Кстати, если вам не нравится темная тема, то вы можете поменять тему на светлую. Сделать это очень просто. Необходимо в файле App.xaml в свойствах корневого xaml элемента указать:
RequestedTheme="Light"
В результате это будет выглядеть похоже на следующий код:
<Application
x:Class="ИмяВашегоПриложения.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ИмяВашегоПриложения "
xmlns:localData="using:ИмяВашегоПриложенияData"
RequestedTheme="Light">
А запущенное приложение станет выглядеть похоже на:
В качестве дополнительной работы можно творчески поработать с шаблоном отображения элемента на главной странице и сделать его, например таким:
<DataTemplate x:Key="CustomItemTemplate">
<Grid HorizontalAlignment="Left">
<Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
<Image Source="{Binding Image}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
</Border>
<Border BorderBrush="#FF59C102" BorderThickness="2"/>
<StackPanel Background="#FF59C102" VerticalAlignment="Bottom">
<TextBlock Text="{Binding Title}" Foreground="White" Style="{StaticResource ExtendedTitleTextStyle}"
Margin="15,8,15,15" FontSize="14.667" FontWeight="Normal" LineHeight="16" />
</StackPanel>
</Grid>
</DataTemplate>
Тогда, ваш клиент будет выглядеть еще более привлекательно:
Задание: продолжая проект, полученный в результате выполнения первого практического задания, измените внешний вид приложения в соответствии со спецификой выбранной темы (источников данных) и рекомендациями ниже.
Первое практическое задание мы закончили на приложении, которое выглядит примерно следующим образом:
Это стандартная темная тема приложения с темным фоном и светлым шрифтом. В своем приложении вы можете как целиком переопределить цветовую схему используя CSS, так и отталкиваться от базовой темы, изменяя лишь отдельные детали.
Windows Library for JavaScript, подключаемая по умолчанию во всех шаблонах, предоставляет вам две готовые темы: светлую и темную, описанные соответственно в файлах ui-light.css и ui-dark.css.
В заголовке каждой станицы вы легко найдете соответствующие ссылки:
<link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" />
Чтобы заменить темную тему на светлую, замените везде ui-dark.css на ui-light.css:
Для начала давайте попробуем разобраться, как данные попадают на страницы. Для этого используется связывание данных (Data-Binding). В WinJS для этого есть специальные шаблоны, которые описываются через data-атрибуты как WinJS.Binding.Template.
Откройте страницу groupedItems.html и найдите описание шаблона с классом "itemtemplate":
<div class="itemtemplate" data-win-control="WinJS.Binding.Template">
<div class="item">
<img class="item-image" src="#" data-win-bind="src: backgroundImage; alt: title" />
<div class="item-overlay">
<h4 class="item-title" data-win-bind="textContent: title"></h4>
<h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: subtitle"></h6>
</div>
</div>
</div>
Этот шаблон используется для отображения плиток на главной странице приложения. Через data-win-bind атрибуты в нем прописано, как данные должны проецироваться на отображение, точнее в какие атрибуты html-элементов они должны быть прописаны при выполнении приложения.
Названия полей данных (в примере выше, это, например, backgroundImage, title, subtitle) соответствуют описанию данных в коде на JavaScript.
Откройте файл groupedItems.js и найдите функцию _initializeLayout—в ней как раз указывается, какой источник данных нужно использовать при наполнении нашего listView и далее в шаблонах:
listView.itemDataSource = Data.items.dataSource;
В свою очередь Data – это глобально доступный объект, определенный в файле data.js, который определяли в первом практическом упражнении. Давайте вернемся к этому файлу, чтобы доопределить недостающие нам данные (например, ссылку на изображение).
Перейдите к функции getItemsFromRSSFeed, занимающейся разбором отдельных постов. Добавьте перед строчкой "var postItem = {" следующий код:
var tempElement = document.createElement("div");
tempElement.innerHTML = postContent;
var image = tempElement.querySelector("img");
var imglink = (image != null) ? "url('" + image.src + "')" : "";
Здесь мы создаем временный элемент с контентом поста и извлекаем (querySelector) из него первую же картинку, чтобы использовать ее в качестве фоновой на плитках к постам. В случае, если картинки нет, используем пустую строку, которую передадим в соответствующее правило CSS.
Замечание: здесь мы также можем попасть в ситуацию, когда явной картинки в посте нет, но есть невидимая, применяемая для подсчета числа просмотров. Именно такая ситуация имеет место для блогов, используемых в ходе статьи, однако, эти картинки прозрачные, поэтому в нашем случае это не критично.
Добавьте в объект-описание поста (postItem) следующие строчки в конце, не забыв добавить запятую строчкой выше:
backgroundImage: imglink
Должно получиться примерно вот так:
var postItem = {
...
link: post.querySelector("link").textContent,
backgroundImage: imglink
};
Если вы сейчас запустите проект на отладку, вы увидите, что визуально ничего не поменялось.
Вернитесь в файл pages\groupedItems\groupedItems.html к нашему шаблону itemtemplate. Двумя строчками ниже вы увидите описание картинки:
<img class="item-image" src="#" data-win-bind="src: backgroundImage; alt: title" />
Если вы знакомы с основами HTML, вы наверняка уже догадались, почему в отображении ничего не поменялось: формат, который мы использовали выше, рассчитан на использование в CSS, а не явную вставку ссылки на изображение через img.
Замечание: одна из причин, почему в данном случае CSS является предпочтительнее, заключается в более гибких настройках отображения и, в частности, наличие возможности манипуляций с изображением, в том числе с сохранением пропорций.
Удалите эту строчку для вставки изображения.
Поднимитесь на уровень выше и добавьте в строчке:
<div class="item">
связывание данных для фонового изображение через соответствующее свойство в CSS:
<div class="item" data-win-bind="style.backgroundImage: backgroundImage">
Попробуйте запустить приложение на отладку:
Стало лучше, но по-прежнему не очень. Например, что вполне ожидаемо, в некоторых постах нет изображений — и вместо них мы получили отсутствие картинок или пустые заглушки. Давайте для таких постов поставим цветной фон. Для этого откройте в той же папке файл groupedItems.css.
Найдите следующую строчку, описывающую отображение отдельного элемента:
.groupeditemspage .groupeditemslist .item {
-ms-grid-columns: 1fr;
-ms-grid-rows: 1fr 90px;
display: -ms-grid;
height: 250px;
width: 250px;
}
Добавьте в конце этого CSS-правила описание фона:
background-color: rgb(0, 204, 255);
Дополнительно можно сделать еще несколько манипуляций над фоновым изображением, например, центрировать его, отменить повторения и задать режим масштабирования:
background-position: 50% 50%; background-repeat: no-repeat; background-size: cover;
Запускаем приложение:
Теперь давайте перейдем к исправлению отображения текстового содержимого.
Вернитесь к файлу groupedItems.html и описанию шаблона элемента (itemtemplate). В конце элемента вы найдете описание подзаголовка (item-subtitle). В нашем случае никакого подзаголовка нет, зато есть дата, поэтому замените эту строчку:
<h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: subtitle"></h6>
на следующие:
<h6 class="item-date win-type-ellipsis">
<span data-win-bind="textContent: day"></span>
<span data-win-bind="textContent: month"></span>
</h6>
Здесь мы также используем связывание с доступными нам полями в описании каждого поста: day и month. Аналогично вы можете определить любые другие необходимые поля и использовать их в отображении объектов.
Если вы попробуете сейчас запустить, вы увидите, что дата куда-то съехала и залезла на заголовок.
Чтобы это поправить, перейдите назад к CSS-файлу. Найдите описание подзаголовка:
.groupeditemspage .groupeditemslist .item .item-overlay .item-subtitle {
-ms-grid-row: 2;
width: 220px;
}
Замените его на соответствующее описание отображение даты:
.groupeditemspage .groupeditemslist .item .item-overlay .item-date {
-ms-grid-row: 2;
width: 220px;
text-transform: uppercase;
text-align:right;
}
В данном случае мы также добавили выравнивание по правому краю и отображение текста в верхнем регистре.
Замечание: обратите внимание, что для позиционирования элементов использует модуль CSS 3 Grid Layout. Мы не будем останавливаться на деталях его использования, но если вы планируете создавать приложения для Windows Store на HTML/JS, рекомендуем хорошо изучить его возможности.
Теперь давайте попробуем сделать заголовок записи побольше и изменить его положение на плитке.
Для начала его необходимо вынести на уровень выше. Перейдите к файлу groupedItems.html и внутри шаблона элемента вынесите описание заголовка на уровень выше, добавив обертку. Должно получиться примерно так:
<div class="item" data-win-bind="style.backgroundImage: backgroundImage">
<!-- Заголовок -->
<div class="item-title-container">
<h4 class="item-title" data-win-bind="textContent: title"></h4>
</div>
<div class="item-overlay">
<h6 class="item-date win-type-ellipsis">
<span data-win-bind="textContent: day"></span>
<span data-win-bind="textContent: month"></span>
</h6>
</div>
</div>
Вернитесь к CSS-файлу, в нем необходимо отобразить изменение иерархии и прописать обновленные стили.
После правила .groupeditemspage .groupeditemslist .item { … } добавьте новое:
.groupeditemspage .groupeditemslist .item .item-title-container {
-ms-grid-row: 1;
margin: 10px;
padding: 8px;
opacity: 0.85;
}
Сразу после него перенесите находящееся ниже описание заголовка (.item-overlay надо заменить на .item-title-container):
.groupeditemspage .groupeditemslist .item .item-title-container .item-title {
overflow: hidden;
display: inline;
font-size: 1.6em;
line-height: 1.5em;
font-family: 'Segoe UI Light';
background: rgb(145, 0, 145);
box-shadow: rgb(145, 0, 145) 0 0 0 8px;
color: white;
}
Попробуйте запустить проект:
Чтобы убрать подложку, оставшуюся от изначального макета, перейдите ниже по коду в CSS-файле к строчкам (оно находится внутри media query – описания):
.groupeditemspage .groupeditemslist .item .item-overlay {
background: rgba(0,0,0,0.65);
}
Замените указанный цвет на transparent.
Попробуйте самостоятельно увеличить размер текста у даты и поменять шрифт на "Segoe UI Semibold" и название приложения на другое. Самостоятельно попробуйте поменять внешний вид заголовков, чтобы они приняли примерно такой вид (это может быть удобнее делать в Expression Blend):
Подберите наиболее подходящий индивидуальный стиль для вашего приложения.
Аналогично тому, как мы изменили внешний вид основной странице приложения к тому же стилю необходимо привести и внутренние страницы (группа и индивидуальная страница для каждого элемента контента).
Сделайте это самостоятельно на свое усмотрение. Например, для блогов, посвященных Windows это могло бы выглядеть так:
Переведите приложение в Snapped-режим (если вы работаете в Expression Blend, на вкладке Device можно менять режим отображения). Здесь также нужно поправить стили с учетом выбранной стилистики.
Причем корректность отображения необходимо проверить для всех внутренних экранов.
Стили для Snap-режима корректируются с помощью Media Queries:
@media screen and (-ms-view-state: snapped) {
...
}
Если вы попробуете еще раз проследить, как получаются и отображаются данные, вы легко заметите, что мы их никак не ограничиваем. Приложение получает на входе потоки данных из RSS, преобразовывает их во внутреннюю структуру, используемую для связывания данных, и далее проецирует их в коллекцию на экране. Фактически, мы сразу видим все-все данные прямо с первого экрана.
В конечном счете, в нашем случае вместо того, чтобы показывать быстро и целиком всю картину последних событий, для чего было бы достаточным выводить 6-8 последних записей, мы сразу обрушиваем на пользователя весь поток новостей. Большой набор данных также не дает возможности быстро переключаться на соседние группы — приходится слишком долго прокручивать (забегая сильно вперед, скажу, что частично эту проблему сглаживает Semantic Zoom).
Таким образом, наша первоочередная задача — ограничить поток данных на первом экране.
Для этого откройте файл pages\groupedItems\groupedItems.js.
В начале функции в области переменных создайте еще две:
var groupedItems; var tilesLimit = 6;
В первой мы будем хранить отфильтрованную коллекцию. Вторая указывает, сколько максимум плиток можно выводить (в идеале, подобные параметры нужно выносить в отдельные файлы настроек или аналогичные структуры данных, описывающих параметры проекта).
Далее найдите следующую строчку:
_initializeLayout: function (listView, viewState) {
Эта функция вызывается при инициализации страницы и прописывает, какие данные необходимо вывести на экран в зависимости от используемого режима отображения. В качестве источника данных используется глобальный объект Data, описанный в файле data.js.
Добавьте в начале функции следующие строчки:
groupedItems = Data.items.createFiltered(function (item) {
return item.index < tilesLimit;
}).createGrouped(
function groupKeySelector(item) { return item.group.key; },
function groupDataSelector(item) { return item.group; }
);
Напомню, что в свойстве items объекта Data прописана коллекция данных (WinJS.Binding.List), сгруппированных по принадлежности к тем или иным RSS-потокам.
Чтобы отфильтровать данные, мы берем эту коллекцию и оставляем только элементы, индекс которых меньше нашего ограничения, после чего заново группируем коллекцию в соответствии с группами.
Замечание: в данном случае мы явно ограничиваем количество элементов шестью (tilesLimit), однако, в общем случае это неправильный подход. На большом мониторе количество плиток может оказаться меньше желаемого, к тому же могут появляться одиноко висящие плитки в конце списка. Самое правильное: динамически рассчитывать лимит в зависимости от доступного пространства.
Далее в этой же функции замените встречающиеся ниже ссылки на Data и Data.items на переменную groupedItems:
if (viewState === appViewState.snapped) {
listView.itemDataSource = groupedItems.groups.dataSource;
listView.groupDataSource = null;
listView.layout = new ui.ListLayout();
} else {
listView.itemDataSource = groupedItems.dataSource;
listView.groupDataSource = groupedItems.groups.dataSource;
listView.layout = new ui.GridLayout({ groupHeaderPosition: "top" });
}
Аналогичную операцию проделайте внутри функции _itemInvoked:
_itemInvoked: function (args) {
if (appView.value === appViewState.snapped) {
// If the page is snapped, the user invoked a group.
var group = groupedItems.groups.getAt(args.detail.itemIndex);
this.navigateToGroup(group.key);
} else {
// If the page is not snapped, the user invoked an item.
var item = groupedItems.getAt(args.detail.itemIndex);
nav.navigate("/pages/itemDetail/itemDetail.html", { item: Data.getItemReference(item) });
}
}
Запустите проект:
Отлично! Теперь мы сразу видим все самое свежее.
Если вы хотите дополнительно разнообразить внешний вид вашего приложения, попробуйте добавить поддержку плиток разного размера.
Как это сделать, описано в этом руководстве: http://msdn.microsoft.com/ru-ru/library/windows/apps/jj657974.aspx.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.