Выпуск Windows 8 Release Preview (RP) вышел, и вы можете скачать его здесь:
http://windows.microsoft.com/en-US/windows-8/release-preview
Тогда очевидно, что я должен перенести моего маленького UrzaGatherer для предварительного просмотра.
Я также пользуюсь этой возможностью, чтобы поговорить о некоторых добавленных мной обновлениях, таких как поддержка привязки данных.
С полной версией можно ознакомиться здесь:
http://www.catuhe.com/MSDN/urza/day5.zip
Ну и конечно же все предыдущие эпизоды:
Портирование в Release Preview
Чтобы помочь вам перенести собственное приложение, мы (в Microsoft) выпустили отличный документ:
http://go.microsoft.com/fwlink/?LinkId=251943
Кроме того, я предлагаю вам прочитать следующий блог, где команда разработчиков Windows 8 рассказывает о различиях между CP и RP:
http://blogs.msdn.com/b/windowsappdev/archive/2012/05/31/what-s -Изменен-для-приложения-разработчиков-Since-на-потребительского preview.aspx
С моей точки зрения, вот основные проблемы, с которыми я столкнулся:
Новый навигатор.js
Первый момент касается файла navigator.js, в который я добавил несколько интересных новинок.
Прежде всего, я добавил анимацию в процессе навигации. Я также добавил новую функцию на страницах с названием afterPageEnter . Эта функция вызывается при воспроизведении анимации enterPage . Это позволяет запускать ваш код, когда все будет готово. Но это также позволяет вашим анимациям получать всю мощь, чтобы поддерживать их плавность даже на небольших компьютерах:
_navigated: function (args) { var that = this; var newElement = that._createPageElement(); var parentedComplete; var parented = new WinJS.Promise(function (c) { parentedComplete = c; }); args.detail.setPromise( WinJS.Promise.timeout().then(function () { if (that.pageElement.winControl && that.pageElement.winControl.unload) { that.pageElement.winControl.unload(); } return WinJS.UI.Pages.render(args.detail.location, newElement, args.detail.state, parented); }).then(function parentElement(control) { that._previousPage = newElement.winControl; that.element.appendChild(newElement); that.element.removeChild(that.pageElement); parentedComplete(); var offset = { top: "0px", left: "50px" }; var enterPage = WinJS.UI.Animation.enterPage(newElement, offset); enterPage.then(function () { document.body.focus(); that.navigated(); setImmediate(function () { if (that._previousPage.afterPageEnter) { that._previousPage.afterPageEnter(newElement); } }); }); }) ); },
Полный новый файл navigator.js доступен здесь:
http://www.catuhe.com/MSDN/Urza/Navigator.zip
Страница по умолчанию
Теперь первая страница вашего проекта должна выглядеть примерно так:
(function () { "use strict"; var app = WinJS.Application; var nav = WinJS.Navigation; var ui = WinJS.UI; … app.onactivated = function (eventObject) { if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch || eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.search || eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.fileOpenPicker) { eventObject.setPromise(WinJS.UI.processAll().then(function () { WinJS.Resources.processAll().then(function () { … if (nav.location) { nav.history.current.initialPlaceholder = true; return nav.navigate(nav.location, nav.state); } else { return nav.navigate(UrzaGatherer.navigator.home); } }); })); } }; app.oncheckpoint = function (args) { }; app.start(); })();
Активация приложения теперь обрабатывается обещанием, представленным аргументом события onactivation . Навигация также запускается вашим кодом с помощью функции nav.navigate .
Многомерный список просмотра
Другим важным моментом является новый способ, используемый для определения многомерных списков.
listView.layout= new ui.GridLayout({ groupInfo: function () { return { enableCellSpanning: true, cellWidth: 28, cellHeight: 13 }; } });
Это новое наименование было создано для того, чтобы подчеркнуть тот факт, что каждый элемент должен иметь пропорциональный размер относительно указанного размера ячейки ( cellWidth / cellHeight ).
Обходной путь ошибки Semantic Zoom
Release Preview не является окончательной версией, поэтому могут быть найдены небольшие ошибки.
Один из них было действительно трудно исправить, поэтому я решил поделиться с вами решением
На главной странице присутствует семантический зум. При определенных обстоятельствах (связанных с мощностью компьютера) базовый listView просто не отображается. Очевидно, что это не воспроизводится в режиме отладки (круто!) И не каждый раз (опять круто!).
После целого дня борьбы я, наконец, нашел обходной путь: после настройки источников данных, вам просто нужно снова запустить процесс компоновки семантического управления масштабированием:
var zoomedListView = element.querySelector(".zoomedList").winControl; var groupDataSource = UrzaGatherer.ExpansionsListWithCardOfTheDay.createGrouped( this.groupKeySelector, this.groupDataSelector, this.groupCompare); listView.itemDataSource = groupDataSource.dataSource; listView.groupDataSource = groupDataSource.groups.dataSource; zoomedListView.itemDataSource = groupDataSource.groups.dataSource; if (onlyOnce) element.querySelector(".zoomControl").winControl.forceLayout();
Обратите внимание на использование переменной onlyOnce, чтобы быть уверенным, что вы применяете патч только в первый раз.
Волшебство setImmediate
Последним важным моментом этой миграции является понимание функции setImmediate (или msSetImmediate ):
http://msdn.microsoft.com/en-us/library/windows/apps/hh453394.aspx
Эта функция используется для выполнения вашего кода сразу после текущего блока, а также сразу после любых оставшихся операций (анимация, пользовательский интерфейс и т. Д.).
Это будет действительно полезно для решения некоторых специфических проблем, таких как, например, «щелчок мертвым», когда ваши пользователи слишком быстро нажимают кнопку «назад». Действительно, в этом случае использование setImmediate позволяет вам вернуться на предыдущую страницу, но после завершения рендеринга страницы (если вы этого не сделаете, WinJS может попытаться манипулировать некоторыми расположенными элементами пользовательского интерфейса).
Чтобы учесть эту проблему, я обновил файл navigator.js , чтобы изменить обработчик нажатия кнопки «Назад»:
if (backButton) { backButton.onclick = function () { setImmediate(function () { nav.back(); }); }; if (nav.canGoBack) { backButton.removeAttribute("disabled"); } else { backButton.setAttribute("disabled", "disabled"); } }
Другой пример можно найти в коде, используемом для прокрутки:
setImmediate(function () { if (currentIndex) listView.indexOfFirstVisible = currentIndex; });
Добавление привязки с WinJS.Binding.as
Я не охватывал привязку данных в предыдущих эпизодах. Это действительно важный момент, и, наконец, я широко использовал его в UrzaGatherer.
Например, я хотел добавить случайную карту на главном экране, и я хотел менять карту каждые две минуты:
Для этого я создал список привязок со всеми расширениями. Я добавил в этот список конкретный объект, используемый для представления случайной карты.
Чтобы сделать эту карту привязываемой (я имею в виду: каждое изменение, примененное к карте, автоматически синхронизируется с пользовательским интерфейсом), это действительно просто, потому что вам просто нужно использовать класс WinJS.Binding.as :
var bindableCard = new WinJS.Binding.as(card); expansion.cardsList.push(bindableCard); Using this class, you create a completely bindable object. <div class="cardOfTheDayTemplate" data-win-control="WinJS.Binding.Template"> <div class="card-image-container" data-win-control="UrzaGatherer.Tools.DelayImageLoader" data-win-options="{root: 'cards'}"> <img class="card-image" data-win-bind="src: url" src="#" /> </div> <div class="card-overlay"> </div> <h4 class="card-title" data-win-bind="textContent: name"></h4> <div class="item-border"> </div> <div class="item-check" data-win-bind="style.display: card.isChecked UrzaGatherer.Tools.BoolToDisplayConverter"> <div class="checkBackground"></div> <div class="checkmark"></div> </div> </div>
Все основано на данных-win-bind . Шаблоны, используемые списками, полностью совместимы с этим объектом, и когда свойство объекта изменяется, пользовательский интерфейс отвечает автоматически (как в XAML !!):
var updateCardOfTheDay = function () { var card; do { var cardNumber = Math.floor(Math.random() * cards.length); card = cards[cardNumber]; } while (card.size.isPlane); if (cardOfTheDayBinding.element) { WinJS.Utilities.query("img", cardOfTheDayBinding.element).forEach(function (img) { WinJS.Utilities.removeClass(img, "loaded"); }); } cardOfTheDayBinding.url = card.logo; cardOfTheDayBinding.name = card.name; cardOfTheDayBinding.card = card; }
Благодаря этой превосходной технологии я решил обновить все свои шаблоны. Так, например, когда пользователь выбирает использование локальных или удаленных файлов, мне просто нужно изменить соответствующие свойства моих объектов:
var updateBlockOfflineState = function (block, offline) { if (offlineMode) { block.logo = "ms-appdata:///local/blocks/" + block.name.replace(":", "_") + ".png"; block.banner = "ms-appdata:///local/blocks/" + block.name.replace(":", "_") + "_banner.png"; } else { block.logo = root + "/blocks/" + block.name.replace(":", "_") + ".png"; block.banner = root + "/blocks/" + block.name.replace(":", "_") + "_banner.png"; } }
Это оно!!
Это оно! Вы сделали. Приложение можно опубликовать в магазине (уже сделано для UrzaGatherer: http://apps.microsoft.com/webpdp/app/urzagatherer/92adce33-8490-4af7-9392-9c35c91d8a37 ).
Теперь не стесняйтесь использовать мои учебники в качестве основы для вашего проекта. Вы почти готовы сейчас