共用方式為


如何在 ListView 中啟用重新排序、拖曳和放下功能

[ 本文的目標對象是撰寫 Windows 執行階段 App 的 Windows 8.x 和 Windows Phone 8.x 開發人員。如果您正在開發適用於 Windows 10 的 App,請參閱 最新文件 ]

了解如何將重新排序、拖曳和放下項目功能新增到 ListView 控制項。 (僅限 Windows)

您必須知道的事

技術

先決條件

  • 您必須能夠使用 JavaScript,以 WinJS 控制項建立基本的 Windows 市集應用程式。如需如何開始使用 WinJS 控制項的指示,請參閱快速入門:新增 WinJS 控制項與樣式

  • 在新增其他功能之前,您應該了解如何建立基本的 ListView 控制項。如需如何建立簡單 ListView 的快速概觀,請參閱快速入門:新增 ListView 或檢閱 ListView 控制項參考。

指示

步驟 1: 設定範例

本範例示範如何建立 ListView 控制項與 ItemContainer,以便在清單中顯示項目的相關資訊。

使用下列 HTML 標記做為 ListView 控制項的基礎。您可以在 Microsoft Visual Studio 2013 中,將程式碼複製並貼到 [空白應用程式] 中的 default.html 檔案。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>List_View_demo</title>

    <!-- WinJS references -->
    <link href="//Microsoft.WinJS.2.0/css/ui-dark.css" rel="stylesheet" />
    <script src="//Microsoft.WinJS.2.0/js/base.js"></script>
    <script src="//Microsoft.WinJS.2.0/js/ui.js"></script>

    <!-- List_View_demo references -->
    <link href="/css/default.css" rel="stylesheet" />
    <script src="/js/default.js"></script>
    <script src="js/data.js"></script>
</head>
<body>
    <div id="listViewTemplate">
        <div id="listTemplate" 
            data-win-control="WinJS.Binding.Template">
            <div class="listTemplate">
                <div>
                    <h4 data-win-bind="innerText: title"></h4>
                    <h6 data-win-bind="innerText: text"></h6>
                </div>
            </div>
        </div>
        <div id="listView" 
             data-win-control="WinJS.UI.ListView"
             data-win-options="{
                itemDataSource : DataExample.itemList.dataSource,
                itemTemplate: select('#listTemplate'),
                itemsDraggable: true,
                itemsReorderable: true,
                layout: { type: WinJS.UI.GridLayout }
             }">
        </div>
    </div>
    <div id="listViewDetail" >
        <h2>Details</h2><br/><br/>
        <div id="listViewDetailInfo" 
             draggable="true"
             data-win-control="WinJS.UI.ItemContainer">
            <h4>Cherry chocolate swirl</h4>
            <h6>Ice cream</h6>
            <p>Description: 
                <span>A sumptious blending of cherry 
                and dark chocolate.</span>
            </p>
        </div>
    </div>
</body>
</html>

此範例也使用 CSS 樣式來調整 HTML 頁面上的 ListView 控制項和 ItemContainer。將下列 CSS 程式碼新增到與 ListView 控制項 (在 [空白應用程式] 範本中的 css/default.css) 關聯的樣式表。


/* Layout the app page as a grid. */
body {
    display: -ms-grid;
    -ms-grid-columns: 600px 1fr;
    -ms-grid-rows: 1fr;
}

/* Style the template for the ListView control.
.listTemplate {
    width: 282px;
    height: 70px;
    padding: 5px;
    overflow: hidden;
}

.listTemplate div {
    margin: 5px;
}

/* Style the ListView control. */
#listView {
    -ms-grid-column: 1;
    -ms-grid-row: 1;
    height: 500px; 
    width: 500px; 
    border: 2px solid gray;
}

#listView .win-container {
    margin: 10px;
}

#listView .win-container:hover {
    color: red;
}

/* Style the ItemContainer control.*/
#listViewDetail {
    -ms-grid-column: 2;
    -ms-grid-row: 1;
}

#listViewDetailInfo {
    width: 300px;
}

此範例使用一些預先定義的資料來填入 ListView 控制項。這些資料包含在名為 'data.js' 的檔案中,該檔案位於 [js] 資料夾 (js/data.js)。使用下列指示將 ListView 資料新增到應用程式。

Dn423315.wedge(zh-tw,WIN.10).gif將 JavaScript 資料檔案新增到您的應用程式

  1. 在 [方案總管] 中,用滑鼠右鍵按一下 [js]**** 資料夾,然後選擇 [加入] > [新增 JavaScript 檔]****。

  2. 在 [加入新項目] 對話方塊的 [名稱]**** 方塊中,輸入 'data.js',然後按一下 [加入]。

  3. 在 [方案總管]**** 中,按兩下新的 JavaScript 檔案並新增下列程式碼。

    (function () {
        "use strict";
    
        // Define the dataset.
        var dataArray = [
            { title: "Basic banana", 
              text: "Low-fat frozen yogurt", 
              description: "Go bananas for some frozen yogurt." },
            { title: "Banana blast", 
              text: "Ice cream", 
              description: "More banana than allowed by law." },
            { title: "Brilliant banana", 
              text: "Frozen custard", 
              description: "Custard with banana; an excellent desert." },
            { title: "Orange surprise", 
              text: "Sherbet", 
              description: "Orange sherbert with a little extra something." },
            { title: "Original orange", 
              text: "Sherbet", 
              description: "The orange sherbert you know and love." },
            { title: "Vanilla", 
              text: "Ice cream", 
              description: "The one and only, classic vanilla ice cream." },
            { title: "Very vanilla", 
              text: "Frozen custard", 
              description: "What's better than custard with vanilla flavoring?" },
            { title: "Marvelous mint", 
              text: "Gelato", 
              description: "Mint meets gelato in this delicious desert." },
            { title: "Succulent strawberry", 
              text: "Sorbet", 
              description: "A joyful confection of strawberries." }
        ];
    
        // Load the dataset into a List object.
        var dataList = new WinJS.Binding.List(dataArray);
    
        // Expose the List object to the rest of the app.
        WinJS.Namespace.define("DataExample", {
            itemList: dataList
        });
    
    })();
    

注意  您可以用任何所需的資料取代原本提供的資料。若要取代資料來源,您可以變更傳送到 WinJS.Binding.List 建構函式方法的資料集。

如果您決定使用一些資料來源,而不是使用 IListDataSource 物件,則必須實作 moveBeforemoveAftermoveToStart 方法。實際上,建議您使用 WinJS 提供的 List 物件來包裝您的資料來源。

同時請注意,應用程式的 HTML 標記中定義的 Template 物件會取用包含具有 titletext 屬性之項目的資料來源。如果您的資料不包含 titletext 屬性,則必須調整 Template 物件的定義。

 

步驟 2: 將重新排序功能新增到 ListView 控制項

您可以非常輕鬆地將重新排序功能新增到 ListView 控制項。只需要稍微變更或新增程式碼即可。基本上,您只需要將 ListView 控制項的 itemsReorderable 屬性設為 'true' 即可(預設設定為 'false')。

您可以在控制項的 HTML 標記中以宣告方式執行此動作,也可以使用 JavaScript 在執行階段新增此功能。下列範例示範如何藉由調整控制項的 HTML 標記來新增重新排序功能。

<!-- The definition of the ListView control. 
    Note that the data-win-options attribute for the 
    control includes the itemsReorderable property. -->
<div id="listView"
    data-win-control="WinJS.UI.ListView"
    data-win-options="{
        itemDataSource : DataExample.itemList.dataSource,
        itemTemplate: select('#listTemplate'),
        itemsReorderable : true,
        layout: { type : WinJS.UI.GridLayout }
    }">
</div>

下一個範例示範如何使用 JavaScript 在執行階段將重新排序功能新增到 ListView 控制項。

(function () {

    // Other JavaScript code ...

    // Get a reference to the ListView control.
    var listView = 
        document.querySelector('#listView').winControl;

    // Set the controls itemsReorderable property.
    listView.itemsReorderable = true;

    // Other JavaScript code ...

})();

當您變更 ListView 控制項的 itemsReorderable 屬性之後,請執行專案 (按 F5)。在 ListView 中選取一個項目,並將它拖曳到相同 ListView 內的另一個位置。

步驟 3: 將拖曳功能新增到 ListView

基本上,您可以使用與新增重新排序功能一樣簡單的方式,將拖曳功能新增到 ListView 控制項。ListView 控制項包含 itemsDraggable 屬性,您可以在控制項的 HTML 中以宣告方式設定,也可以在執行階段變更。

下列範例說明如何在控制項的 HTML 標記中,將簡單的拖曳功能新增到 ListView

<!-- The definition of the ListView control. 
    Note that  the data-win-options attribute for the 
    control includes the itemsDraggable property. -->
<div id="listView"
    data-win-control="WinJS.UI.ListView"
    data-win-options="{
        itemDataSource : DataExample.itemList.dataSource,
        itemTemplate: select('#listTemplate'),
        itemsDraggable : true,
        layout: { type : WinJS.UI.GridLayout }
    }">
</div>

下一個範例說明如何使用 JavaScript 在執行階段將簡單的拖曳功能新增到 ListView 控制項。

(function () {

    // Other JavaScript code ...

    // Get a reference to the ListView control.
    var listView = 
        document.querySelector('#listView').winControl;

    // Set the controls itemsReorderable property.
    listView.itemsDraggable = true;

    // Other JavaScript code ...

})();

當您將 itemsDraggable 屬性設為 true 之後,請執行應用程式 (按 F5)。在應用程式中,從 ListView 控制項選取項目,並將它拖曳到 ListView 之外。該項目會以半透明方式顯示在 ListView 之外的應用程式介面上。當您放開滑鼠按鈕時,該項目會消失。接著會觸發適當的放置事件。

如果您要與 ListView 控制項的基本資料來源互動,必須同時實作 ListView 某些拖放事件的處理常式。在下列範例中,有一個處理常式已新增到 ListView.itemdragstart 事件,也新增到 dragoverdropItemContainer 事件。

若要在上一個範例中使用此程式碼,請將此程式碼新增到 Blank app 範本 (js/default.js) 提供的 default.js 檔案中所定義的 app.onactivated 事件處理常式。

// Get the data from the ListView when the user drags an item.
listView.addEventListener("itemdragstart", function (evt) {

    // Store the index of the item from the data source of 
    // the ListView in the DataTransfer object of the event.
    evt.detail.dataTransfer.setData("Text",
        JSON.stringify(evt.detail.dragInfo.getIndices()));
});

// Allows the drop to occur. The default behavior disallows
// an element from being dropped upon another.
listViewDetailInfo.addEventListener('dragover', function (evt) {
    evt.preventDefault();
});

// Insert the content (from the ListView) into the ItemContainer.
listViewDetailInfo.addEventListener('drop', function (evt) {

    // Get the index of the selected item out of the event object.
    var dragIndex = JSON.parse(evt.dataTransfer.getData("Text")),
        dataSource = listView.winControl.itemDataSource;

    // Extract the selected data from the data source 
    // connected to the ListView control.
    dataSource.itemFromIndex(Number(dragIndex)).
        then(function (item) {
            if (item) {
                var itemData = item.data;

                // Update the ItemContainer with the data from
                // the item dragged from the ListView control.
                listViewDetailInfo.querySelector('h4').innerText = itemData.title;
                listViewDetailInfo.querySelector('h6').innerText = itemData.text;
                istViewDetailInfo.querySelector('span').innerText = itemData.description;
            }
        });

});

在上一個範例中,從 ListView 拖曳的選取資料已儲存在與 itemdragstart 事件關聯的 DataTransfer 物件中。由於這兩個處理常式都可以存取相同的資料來源,因此只會儲存選取項目的索引。或者,您可以將物件序列化為 DataTransfer 物件中的 JSON 格式字串。

ItemContainerdragover 事件處理常式中,預設行為是禁止的 (預設行為不允許將元素放到另一個元素上)。在 ItemContainer 物件的 drop 事件處理常式中,會從 DataTransfer 物件擷取資料來源之選取項目的索引,然後從 ListView 的資料來源擷取項目。最後,會以新的資料更新 ItemContainer 的 HTML。

注意   如果您的應用程式在群組化的 ListView 控制項中的群組之間重新排序或拖放項目,則必須從資料來源移除項目,然後將它們重新插入新群組中。您無法使用 moveAftermoveBeforemoveToStart 來完成這項作業。

 

步驟 4: 將放下功能新增到 ListView

您可以將放下功能新增到 ListView 控制項,其方法與上一個範例中將放下功能新增到 ItemContainer 控制項的方法類似。

使用下列程式碼範例,將放下資料的功能從 ItemContainer 新增到 ListView

若要在上一個範例中使用此程式碼,請將此程式碼新增到 Blank app 範本 (js/default.js) 提供的 default.js 檔案中所定義的 app.onactivated 事件處理常式。

// Drop content (from the ItemContainer) onto the ListView control.
listView.addEventListener("itemdragdrop", function (evt) {
    if (evt.detail.dataTransfer) {
        var dragData = JSON.parse(
            evt.detail.dataTransfer.getData("Text"));

        // It's a good idea to validate the data before 
        // attempting to insert it into the data source!
        if (dragData && dragData.title && dragData.text) {
            var dropIndex = evt.detail.insertAfterIndex;

            // Insert the new item into the data source.
            DataExample.itemList.splice(dropIndex, 0, {
                title: dragData.title,
                text: dragData.text,
                description: dragData.description
            });
        }
    }
});

// Allows the drop to occur. The default behavior disallows
// an element from being dropped upon another.
listView.addEventListener("itemdragenter", function (evt) {
    if (evt.detail.dataTransfer &&
        evt.detail.dataTransfer.types.contains("Text")) {
        evt.preventDefault();
    }
});

// Drag content from the ItemContainer.
listViewDetailInfo.addEventListener('dragstart', function (evt) {

    // Get the data displayed in the ItemContainer and
    // store it in an anonymous object.
    var target = evt.target,
        title = target.querySelector('h4').innerText,
        text = target.querySelector('h6').innerText,
        description = target.querySelector('span').innerText,
        dragData = {
            source: target.id,
            title: title,
            text: text,
            description: description
        };
    
    // Store the data in the DataTransfer object as a
    // JSON-formatted string.                
    evt.dataTransfer.setData("Text", 
        JSON.stringify(dragData));
});

在前述的程式碼範例中,有一個事件處理常式已新增到 ItemContainerdragstart 事件,也新增到 ListView 控制項的 itemdragenteritemdragdrop 事件。ItemContainer.dragstart 事件的處理常式會從 ItemContainer 擷取資料,並將它以 JSON 格式字串儲存在與該事件關聯的 DataTransfer 物件中。在 ListView.onitemdragenter 事件處理常式中,該事件的預設行為是不允許將 HTML 內容放進 ListView 控制項中。最後,當引發 ListView.onitemdragdrop 事件時,會從 DataTransfer 物件擷取資料,然後插入 ListView 控制項的資料來源中。

注意   如果使用者嘗試使用鍵盤來重新排序 ListView 控制項,則傳送到 itemdragdrop 事件做為引數的 DataTransfer 物件是未定義的。在 itemdragdrop 事件的處理常式中,您必須確定在嘗試讀取 DataTransfer 物件所包含的資料之前,該物件已經存在。

 

備註

如需如何使用 ListView 控制項以及在 ListView 控制項中啟用重新排序、拖曳和放下功能的詳細資訊,請參閱 HTML ListView 拖放和重新排序範例

完整範例

相關主題

HTML ListView 拖放和重新排序範例

控制項