หลังจากเราติดตั้งซอฟต์แวร์ที่จำเป็นเรียบร้อยแล้ว ในตอนนี้เราจะทดลองสร้างแอพลิเคชันให้ผู้ใช้สร้างและแก้ไขไฟล์ข้อความกัน โดยในตอนนี้เราจะเริ่มสร้างหน้าจอหลักๆ กันก่อน
แอพลิเคชันส่วนใหญ่มักจะมีหลายหน้าจอ รวมถึงแอพลิเคชันที่เรากำลังจะสร้างด้วย เพื่อความง่ายเราจะสร้างแอพลิเคชันจากเทมเพลตที่ Visual Studio เตรียมไว้ให้เลย ดังนี้
รอสักครู่เราจะได้โปรเจกต์ตั้งต้นพร้อมหน้าแรก สามารถคลิกปุ่ม Start Debugging (ปุ่มไอคอน play สีเขียวบนแถบเครื่องมือ) เพื่อลองทดสอบได้ทันที
ก่อนจะเริ่มลงมือ เรามาศึกษาโครงสร้างของโปรเจกต์กันก่อน ให้สังเกตที่แถบ Solution Explorer ด้านขวาบนของหน้าจอ ส่วนนั้นจะแสดงส่วนประกอบของโปรเจกต์ ซึ่งมีส่วนหลักๆ ดังนี้
สำหรับไฟล์เว็บเพจ จาวาสคริปต์ สไตล์ชีท และรูปภาพนั้น เราจะกำหนดชื่อและวางไว้ในตำแหน่งใดก็ได้ เนื่องจากเราจะต้องเป็นคนอ้างอิงไฟล์ดังกล่าวเองทั้งหมด เช่นเดียวกับการสร้างเว็บเพจทั่วๆ ไป (เช่น ไฟล์จาวาสคริปต์และสไตล์ชีทต้องใส่ไว้ในแท็ก head ของหน้าเว็บเพจ)
การใช้คอนโทรลพื้นฐาน
หน้าหลักของแอพลิเคชันคือ default.html จะมีเพียง div ที่ทำหน้าที่เป็น PageControlNavigator เพื่อนำหน้าต่างๆ มาแสดงเท่านั้น เราสามารถกำหนดหน้าแรกที่จะเริ่มแสดงผลได้จากที่นี่ โดยตอนแรกโปรเจกต์ได้กำหนดไว้ให้เปิดหน้า /pages/home/home.html
ในส่วนของหน้า /pages/home/home.html นั้นจะมีโครงสร้างหลักๆ ของหน้าอยู่ โดยปกติ
เราจะลองแก้ไขหน้าแรกให้มีปุ่ม New และ Open ดู โดยเปิดไฟล์ /pages/home/home.html และแก้ไขเนื้อหาในแท็ก section ใหม่ดังนี้
{syntaxhighlighter brush: xml}<section aria-label="Main content" role="main">
<button id="newButton">New</button>
<button id="openButton">Open</button>
</section>{/syntaxhighlighter}
ลองสั่งรันแอพลิเคชันดูจะพบปุ่มทั้งสองปรากฎบนหน้าจอแล้ว
จะสังเกตได้ว่า การพัฒนาในเบื้องต้นแทบไม่ต่างจากการสร้างเว็บเพจตามปกติ โดยเราสามารถใช้แท็ก HTML มาตรฐานต่างๆ ในการสร้างแอพลิเคชันได้เลย
การสร้างหน้าใหม่
เราจะทำให้แอพลิเคชันเปลี่ยนหน้าไปยังหน้า editor เมื่อผู้ใช้คลิกปุ่ม New แต่ก่อนอื่นเราจะต้องสร้างหน้า editor ขึ้นมาเสียก่อน โดยทำดังนี้
1. ที่ Solution Explorer คลิกขวาที่โฟลเดอร์ pages จากนั้นเลือกเมนู Add > New Folder แล้วกำหนดชื่อโฟลเดอร์เป็น editor
2. คลิกขวาที่โฟลเดอร์ editor ที่สร้างขึ้นใหม่ จากนั้นเลือกเมนู Add > New Item...
3. เลือก Page Control จากนั้นกำหนดชื่อในช่อง Name เป็น editor.html แล้วกดปุ่ม OK
เราจะได้หน้าใหม่ /pages/editor/editor.html พร้อมไฟล์สไตล์ชีทและจาวาสคริปต์ตั้งต้นแล้ว จากนั้นเพิ่มช่องแก้ไขข้อความลงไปในหน้า โดยเพิ่ม textarea เข้าไป
หมายเหตุ: ในหน้าที่สร้างขึ้นด้วยวิธีนี้ ส่วนหัวของไฟล์ HTML จะไม่ได้เรียกใช้ไฟล์ default.css เราต้องไปเพิ่มแท็ก <link href="/css/default.css" rel="stylesheet"/> เอาเอง
สำหรับผู้ที่ไม่คุ้นเคยกับภาษาจาวาสคริปต์ มีเรื่องที่ต้องทำความเข้าใจเบื้องต้นดังนี้
ในภาษาจาวาสคริปต์ เราสามารถเขียนสคริปต์ได้โดยตรง แต่การเขียนแบบนั้นอาจเกิดปัญหาการประกาศตัวแปรและใช้ตัวแปรกันข้ามไฟล์สคริปต์ได้ ดังนั้นโดยปกติเราจะเขียนโค้ดในฟังก์ชัน จากนั้นเรียกใช้ฟังก์ชันนั้นทันทีอีกทีนึง เช่น
{syntaxhighlighter brush: jscript}(function () {
"use strict";
// Our code goes here...
var myVar = 8;
})();{/syntaxhighlighter}
การเขียนแบบนี้จะทำให้เราประกาศและใช้ตัวแปรได้โดยไม่ต้องกลัวว่าจะมีไฟล์สคริปต์ไฟล์อื่นมากำหนดค่าทับลงไปได้
เมื่อหน้าใหม่พร้อมแล้ว เราจะสั่งให้แอพลิเคชันเปลี่ยนหน้าเมื่อกดปุ่ม New โดยเปิดไฟล์ /pages/home/home.js จะพบโครงสร้างโค้ดที่ใช้กำหนดพฤติกรรมของหน้า ดังนี้
{syntaxhighlighter brush: js}(function () {
"use strict";
WinJS.UI.Pages.define("/pages/test/test.html", {
ready: function (element, options) {
// TODO: Initialize the page here.
},
unload: function () {
// TODO: Respond to navigations away from this page.
},
updateLayout: function (element, viewState, lastViewState) {
// TODO: Respond to changes in viewState.
}
});
})();{/syntaxhighlighter}
ฟังก์ชัน WinJS.UI.Pages.define
จะใช้สำหรับกำหนดให้หน้าเว็บเพจของเรากลายเป็น
PageControl
ได้ โดยอาร์กิวเมนต์แรกระบุที่อยู่ของหน้า ส่วนอาร์กิวเมนต์ที่สองเป็นวัตถุระบุที่มีฟังก์ชันระบุพฤติกรรมต่างๆ ของหน้า
เราจะแก้ไขในฟังก์ชัน ready
ซึ่งจะถูกเรียกเมื่อหน้าถูกสร้างขึ้นเรียบร้อยพร้อมใช้งาน ให้เริ่มฟังอีเวนต์จากปุ่ม newButton
ดังนี้
{syntaxhighlighter brush: js}(function () {
"use strict";
var onNewDocument = function (event) {
WinJS.Navigation.navigate("/pages/editor/editor.html");
};
WinJS.UI.Pages.define("/pages/home/home.html", {
ready: function (element, options) {
var newButton = element.querySelector('#newButton');
newButton.addEventListener("click", onNewDocument);
}
});
})();{/syntaxhighlighter}
ในฟังก์ชัน ready
บรรทัดแรกเราจะหาอีลิเมนต์ที่มีไอดีเป็น
newButton
ก่อน จากนั้นจึงสั่งให้ฟังอีเวนต์ click
หากมีการคลิกให้เรียกฟังก์ชัน onNewDocument
ส่วนฟังก์ชัน onNewDocument
เรียกฟังก์ชัน WinJS.Navigation.navigate
เพื่อเปลี่ยนหน้าไปยังหน้าที่ต้องการ กรณีที่ต้องการส่งค่าไปให้หน้าใหม่ได้ สามารถส่งผ่านอาร์กิวเมนต์ตัวที่สองได้ (ซึ่งเราจะใช้ในตอนต่อๆ ไป)
เสร็จแล้วทดลองรันโปรแกรม เราจะสามารถคลิกปุ่ม New เพื่อไปยังหน้าใหม่ที่เราสร้างได้แล้ว และสามารถคลิกปุ่ม Back เพื่อย้อนกลับมาหน้าเดิมได้ด้วย (ทำงานได้ด้วยซอร์สโค้ดส่วนที่ Visual Studio สร้างไว้ให้เรา)
เราสามารถตกแต่งหน้าตาแอพลิเคชันได้โดยใช้ HTML5/CSS3 พื้นฐาน โดยเราจะเริ่มจากปรับเปลี่ยนสีของแอพลิเคชัน และปรับหน้าตาของปุ่ม New และ Open ใหม่ให้คล้ายคลึงกับ Tile เพื่อไม่ให้หน้าตาดูโล่งเกินไป
สำหรับการปรับสีพื้นหลังนั้นสามารถทำได้ง่ายโดยกำหนดคุณสมบัติของ #contentHost
ในไฟล์ default.css
ส่วนการปรับหน้าตาของปุ่มนั้น เราจะถือโอกาสนี้ทดลองใช้ความสามารถในการจัดวัตถุด้วยกริดกัน
เริ่มต้นจากเปิดไฟล์ /pages/home/home.html
แล้วแก้ไขจากปุ่มเป็น div ที่ครอบด้วยข้อความแทน ดังนี้
{syntaxhighlighter brush: xml}<section aria-label="Main content" role="main">
<div id="newButton" class="tileButton">
<p>New</p>
</div>
<div id="openButton" class="tileButton">
<p>Open</p>
</div>
</section>{/syntaxhighlighter}
จากนั้นตกแต่งหน้าตาปุ่ม โดยกำหนดสไตล์ของคลาส titleButton
ซึ่งทำได้เช่นเดียวกับการตกแต่งหน้าเว็บเพจด้วย CSS3 ทั่วไป ดังนี้
{syntaxhighlighter brush: css}.tileButton {
background: rgb(71, 169, 80);
border: 1px solid rgb(109, 179, 81);
}
.tileButton p {
margin: 10px;
font-weight: 200;
font-size: x-large;
}{/syntaxhighlighter}
จากนั้นเราจะกำหนดให้ปุ่มเรียงกันในกริด ให้เปิดไฟล์ /pages/home/home.css
แล้วกำหนดให้ container (ในที่นี้คืออีลิเมนต์คลาส homepage) ให้เป็น grid container ดังนี้
{syntaxhighlighter brush: css}.homepage section[role=main] {
display: -ms-grid;
-ms-grid-columns: 250px;
-ms-grid-rows: 120px 10px 120px;
margin-top: 60px;
margin-left: 120px;
}{/syntaxhighlighter}
การทำให้อีลิเมนต์กลายเป็น grid container สามารถกำหนดได้โดยใหสไตล้ display มีค่าเป็น -ms-grid; จากนั้นเราสามารถกำหนดได้ว่าจะให้ตัวกริดเรียงตัวอย่างไรโดยใช้สไตล์ -ms-grid-columns และ -ms-grid-rows กำหนดขนาดของแถวและคอลัมน์ทีละอันตามลำดับ โดยเราสามารถกำหนดด้วย px, หรือกำหนดเป็นอัตราส่วนต่อพื้นที่ที่เหลืออยู่ด้วยหน่วย fr, หรือกำหนดเป็น auto เพื่อให้ขนาดเป็นไปตามเนื้อหาของสมาชิกก็ได้
ในที่นี้เรากำหนดให้กริดมีสามแถว สูง 120px, 10px, 120px ตามลำดับ (แถวที่สูง 10px กันไว้เป็นช่องว่างระหว่างปุ่ม) และคอลัมน์เดียวกว้าง 250px ส่วน margin-top และ margin-left กำหนดเพิ่มเติมเพื่อให้ตัวกริดห่างออกมาจากขอบจอ
จากนั้นเราจึงกำหนดให้อีลิเมนต์ในกริดไปประจำในช่องกริด ดังนี้
{syntaxhighlighter brush: css}#newButton {
-ms-grid-row: 1;
-ms-grid-column: 1;
}
-ms-grid-row: 3;
-ms-grid-column: 1;
}{/syntaxhighlighter}
ทดลองรันแอพลิเคชันอีกครั้ง เราจะพบปุ่มมีหน้าตาคล้าย Tile และเรียงกันในกริดแล้ว
เราสามารถตกแต่งหน้าตา และกำหนดอนิเมชันเบื้องต้นให้กับคอนโทรลของเราได้ง่ายๆ โดยใช้ความสามารถของ CSS โดยในที่นี้เราจะกำหนดให้ปุ่มย่อขนาดลง 10% เมื่อถูกกด ทำได้โดยแก้ไขไฟล์ /pages/home/home.css
ดังนี้
{syntaxhighlighter brush: css}.tileButton {
background: rgb(71, 169, 80);
border: 1px solid rgb(109, 179, 81);
-ms-transition: -ms-transform ease-out 0.2s;
-ms-transform: scale(1.0, 1.0);
}
.tileButton:active {
-ms-transform: scale(0.9, 0.9);
}{/syntaxhighlighter}
อีกตัวอย่างหนึ่งคือการกำหนดขนาดของ textarea ในหน้า editor ให้มีขนาดเต็มหน้าจอ โดยใช้ฟังก์ชัน calc ช่วยกำหนดขนาด โดยเปิดไฟล์ /pages/editor/editor.css แล้วเพิ่มเติมโค้ดดังนี้
{syntaxhighlighter brush: css}#contentArea {
font-size: x-large;
/* Clear default margin /
margin: 0;
/ Include padding in width/height /
box-sizing: border-box;
/ Use feature of CSS3 to calculate width and height. /
/ Warning: The space between value and the minus sign is required. /
/ width = 100% - 120px left - 120px right */
width: calc(100% - 240px);
/* 60px is just a magic number for beautifulness */
height: calc(100% - 60px);
}{/syntaxhighlighter}
รายละเอียดเพิ่มเติมเกี่ยวกับการปรับแต่งหน้าตาด้วย CSS สามารถอ่านได้จาก[เอกสารในเว็บไซต์ Microsoft] (http://msdn.microsoft.com/en-us/library/ie/hh673536(v=vs.85).aspx)
โดยปกติผู้ใช้สามารถกำหนดขนาดหน้าจอของแอพลิเคชันได้ 3 state หลักๆ คือ
แบบ Full screen view
แบบ Fill view
แบบ Snapped view
นอกจากนี้หากแอพลิเคชันถูกรันบนแท็บเล็ต ผู้ใช้ก็สามารถหมุนหน้าจอได้อีกด้วย
เพื่อประสบการณ์ที่ดีของผู้ใช้งาน เราควรขนาดและการจัดเรียงคอนโทรลต่างๆ ให้เหมาะสมกับขนาดหน้าจอแต่ละแบบ โดยเราสามารถกำหนดสไตล์ชีทเฉพาะ view state หรือการตั้งหน้าจอก็ได้
วิธีที่ง่ายที่สุดในการเขียนสไตล์ชีทเพื่อแสดงผลหลายหน้าจอ คือกำหนดสไตล์สำหรับขนาดหน้าจอปกติก่อน จากนั้นจึงกำหนดสไตล์สำหรับขนาดหน้าจอเฉพาะแบบ เฉพาะค่าที่ต้องการ override จากขนาดหน้าจอปกติ
ตัวอย่างเช่น ในแอพลิเคชันของเรา ความกว้างของ editor จะไม่เท่ากัน สามารถกำหนดได้ดังนี้
{syntaxhighlighter brush: css}@media screen and (-ms-view-state: snapped) {
.editor section[role=main] {
margin-left: 20px;
}
#contentArea {
/* width = 100% - 20px left - 20px right */
width: calc(100% - 40px);
}
}
@media screen and (-ms-view-state: portrait) {
.editor section[role=main] {
margin-left: 100px;
}
#contentArea {
/* width = 100% - 100px left - 100px right */
width: calc(100% - 200px);
}
}{/syntaxhighlighter}
นอกจากคอนโทรลพื้นฐานใน HTML5 แล้ว ยังมีคอนโทรลอีกจำนวนหนึ่งที่เป็นคอนโทรลเฉพาะของ Windows 8 ที่เราสามารถนำมาใช้ได้
วิธีการเรียกใช้ทำได้โดยการประกาศ div แล้วกำหนดประเภทคอนโทรลที่จะใช้ในแอตทริบิวต์ data-win-control และกำหนดตัวเลือกอื่นๆ ในแอตทริบิวต์ data-win-options
ตัวอย่างการใช้งานแรกที่เราได้เห็นไปแล้ว (แต่ไม่ได้เขียนเอง) นั่นคือ PageControlNavigator ที่ถูกสร้างให้อัตโนมัติใน default.html นั่นเอง
{syntaxhighlighter brush: xml}<div id="contenthost"
data-win-control="Application.PageControlNavigator"
data-win-options="{home: '/pages/home/home.html'}">
</div>{/syntaxhighlighter}
รายการคอนโทรลทั้งหมดสามารถดูได้จากเอกสาร
AppBar นั้นถือเป็นคอนโทรลประเภทหนึ่งในหน้า จึงสามารถสร้างได้โดยการเขียน HTML ตัวอย่างนี้เราจะสร้าง AppBar และเพิ่มปุ่ม Save เข้าไปในหน้า /pages/editor/editor.html
{syntaxhighlighter brush: xml}<div class="editor fragment">
...
<div id="bottomAppBar" data-win-control="WinJS.UI.AppBar">
<button data-win-control="WinJS.UI.AppBarCommand"
data-win-options="{
id: 'saveButton',
label: 'Save',
icon: 'save',
section: 'global'
}">
</button>
</div>
</div>{/syntaxhighlighter}
สำหรับไอคอนที่มีอยู่แล้วในระบบสามารถดูชื่อได้จากเอกสาร
ส่วนวิธีการกำหนดการทำงานเมื่อผู้ใช้คลิกปุ่มก็ไม่ต่างจากปุ่มแบบปกติ คือหานั้นแก้ไขโค้ดในไฟล์ /pages/editor/editor.js
ในที่นี้เราจะกำหนดให้เมื่อผู้ใช้คลิกปุ่ม ให้ปิด AppBar ไปก่อน โดยยังไม่ต้องบันทึกเอกสารจริงๆ
{syntaxhighlighter brush: js}(function () {
"use strict";
var bottomAppBar;
var saveButton;
var onClickSaveButton = function (event) {
bottomAppBar.winControl.hide();
}
WinJS.UI.Pages.define("/pages/editor/editor.html", {
ready: function (element, options) {
bottomAppBar = element.querySelector("#bottomAppBar");
saveButton = element.querySelector("#saveButton");
saveButton.addEventListener("click", onClickSaveButton);
}
});
})();{/syntaxhighlighter}
สังเกตว่าคอนโทรลเฉพาะของ Windows 8 นั้นจะมี property ชื่อ winControl ซึ่งจะมี property และฟังก์ชันต่างๆ ของคอนโทรลให้เรียกใช้งานได้เพิ่มเติมด้วย
ตอนนี้เราสร้างส่วนติดต่อผู้ใช้พื้นฐานได้แล้ว ในตอนต่อไปเราจะศึกษาวงจรชีวิตของแอพลิเคชัน และฟีเจอร์อื่นๆ สำหรับแอพลิเคชันใน Windows 8 App Store ให้มากยิ่งขึ้น ก่อนจะทำให้แอพลิเคชันของเราอ่านและเขียนไฟล์ได้จริงๆ ต่อไป
บทความชุด การเขียนแอพลิเคชันสำหรับ Windows 8 App Store
Comments
C# ก็คงจะคล้ายๆ กัน
น่าสนใจมากครับ
ใครพอทราบเปล่าครับ กำหนด @media screen แบบใน C# ทำยังไง
C# มันไม่มี CCS
ตัวจัดการ UI ของ C# แบบ CSS ใช่มั้ยครับ ลองศึกษาจาก ที่นี่
ตรงหัวข้อ Creating your own styles ครับ
มีอะไรที่เกี่ยวกับ wp8 มาคุยในนี้ได้หมดครับ
ช่วยๆกันแชร์นะครับ คนจะได้เยอะๆ
http://www.facebook.com/groups/wpthailand/
บอทรึเปล่า ฮ่าๆ
เราไม่ใช่บอทนะ เราเป็นคน -*-
พอดีเพิ่งตั้งกรุ้ปใหม่เลยอยากให้คนเข้ามาพูดคุยกันเยอะๆครับ
ถ้าเห็นไม่สมควรลบได้เลยฮะ^^
ที่นี่มีสองอย่างนะครับ คือเตือน กับลบ ซึ่งไม่ใช่ลบที่โพสต์ แต่เป็นลบบัญชี
ถ้าเกิดผมเขียน C# (ในรูปแบบ windows 8 app) มันจะไปรันบน Windows 8 RT ได้รึเปล่าครับ ? พอดีวันนึงผมเคยไปค่าย MS Windows 8 camp มา เห็น staff เขาบอกว่าไม่ได้ ต้องเป็น html5+js แต่บางเว็บบอกว่าได้ครับ แอบสับสนอยู่เล็กน้อย .. :D
ได้ครับ
ขอบคุณครับ :)
ได้ครับ แต่เค้าบอกให้ระวังเวลาเราอิมพอร์ท library สำเร็จรูปบางตัวที่ไม่รู้ว่าคอมไพล์มาจากอะไร
เพราะตัว library ที่แจกๆ กันอาจเขียนกันในภาษาอื่นที่ Windows RT ไม่รู้จัก/ไม่รองรับ
อาจทำให้แอพเรามีปัญหาเวลาไปรันบน Windows RT ได้
Achievement Unlocked: Being a Blognone's Writer
โอเคครับ .. แล้วเรื่องประสิทธิภาพ ระหว่างใช้พวกภาษาจาก .net กับ html5 + js ต่างกันเยอะไหมครับ ?
ปล.ตอนนี้ app ใน store มีเยอะหรือยังครับ ? ลงตั้งแต่ยังเป็นตัวแจกฟรี ตอนนี้ห่างหายไปนานเลยครับ
เรื่องประสิทธิภาพผมไม่ทราบอ่ะครับ ไม่ได้รู้ลึกขนาดนั้น
ผมเองก็รู้เรื่องเขียนแอพ Windows 8 จากการเข้าร่วมงานที่ Microsoft จัดเหมือนกัน
ส่วน Windows Store แตะหลัก 20,000 แอพแล้ว
Achievement Unlocked: Being a Blognone's Writer
ผมชอบ XAML C# กว่าครับ
พื้นฐานโดยรวม ง่ายไม่มีเปลี่ยน ติดตามดูตอนต่อไปครับ
Coder | Designer | Thinker | Blogger