So wird's gemacht: Ermöglichen des Neuanordnens, Ziehens und Ablegens in einem ListView-Steuerelement
[ Dieser Artikel richtet sich an Windows 8.x- und Windows Phone 8.x-Entwickler, die Windows-Runtime-Apps schreiben. Wenn Sie für Windows 10 entwickeln, finden Sie weitere Informationen unter neueste Dokumentation ]
Hier erfahren Sie, wie Sie einem ListView-Steuerelement ein Feature zum Neuanordnen, Ziehen und Ablegen von Elementen hinzufügen. (Nur Windows)
Wissenswertes
Technologien
Voraussetzungen
Sie sollten mit der Erstellung einer einfachen Windows Store-App mit JavaScript vertraut sein, die WinJS-Steuerelemente verwendet. Eine Anleitung zum Einstieg in die Arbeit mit WinJS-Steuerelementen finden Sie unter Schnellstart: Hinzufügen von WinJS-Steuerelementen und -Stilen.
Bevor Sie zusätzliche Funktionen hinzufügen, sollten Sie wissen, wie Sie ein einfaches ListView-Steuerelement erstellen. Eine kurze Übersicht über die Erstellung eines einfachen ListView-Steuerelements finden Sie unter Schnellstart: Hinzufügen von ListView-Steuerelementen oder in der Referenz zum ListView-Steuerelement.
Anweisungen
Schritt 1: Einrichten des Beispiels
In diesem Beispiel wird veranschaulicht, wie Sie ein ListView-Steuerelement und einen ItemContainer zum Anzeigen von Informationen zu einem Element in der Liste erstellen.
Nutzen Sie das folgende HTML-Markup als Grundlage für das ListView-Steuerelement. Sie können den Code kopieren und in die default.html-Datei innerhalb einer Leeren App in Microsoft Visual Studio 2013 einfügen.
<!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>
Im Beispiel werden außerdem CSS-Formate verwendet, um das ListView-Steuerelement und den ItemContainer auf der HTML-Seite anzupassen. Fügen Sie den folgenden CSS-Code dem Stylesheet hinzu, das dem ListView-Steuerelement zugeordnet ist (css/default.css in der Vorlage Leere App).
/* 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;
}
Im Beispiel werden vordefinierte Daten zum Auffüllen des ListView-Steuerelements verwendet. Die Daten sind in einer Datei mit dem Namen "data.js" im Ordner js enthalten (js/data.js). Nutzen Sie die folgenden Anleitungen, um der App die ListView-Daten hinzuzufügen.
So fügen Sie der App eine JavaScript-Datendatei hinzu
Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Ordner js, und wählen Sie Hinzufügen und dann JavaScript-Datei.
Geben Sie im Dialogfeld Neues Element hinzufügen im Feld Name den Text "data.js" ein, und klicken Sie auf Hinzufügen.
Doppelklicken Sie im Projektmappen-Explorer auf die neue JavaScript-Datei, und fügen Sie den folgenden Code hinzu.
(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 }); })();
Hinweis Sie können die bereitgestellten Daten durch die von Ihnen benötigten Daten ersetzen. Zum Ersetzen der Datenquelle können Sie das Dataset ändern, das an die WinJS.Binding.List-Konstruktormethode übergeben wird.
Wenn Sie sich gegen das IListDataSource-Objekt und für die Verwendung einer anderen Datenquelle entscheiden, müssen vom Objekt die Methoden moveBefore, moveAfter und moveToStart implementiert werden. Für die Praxis wird empfohlen, zum Umschließen der Datenquelle das von WinJS bereitgestellte List-Objekt zu verwenden.
Beachten Sie auch, dass das im HTML-Markup für die App definierte Template-Objekt eine Datenquelle verwendet, die Elemente mit den Eigenschaften title
und text
enthält. Falls Ihre Daten die Eigenschaften title
und text
nicht enthalten, müssen Sie die Definition des Template-Objekts anpassen.
Schritt 2: Hinzufügen von Neuanordnungsfunktionen zum ListView-Steuerelement
Das Hinzufügen von Neuanordnungsfunktionen zu einem ListView-Steuerelement ist sehr einfach. Dazu ist im Code nur eine geringfügige Änderung bzw. Hinzufügung erforderlich. Sie müssen praktisch nur die itemsReorderable-Eigenschaft für das ListView-Steuerelement auf "true" festlegen. (Die Standardeinstellung ist "false".)
Sie können dies deklarativ im HTML-Markup für das Steuerelement durchführen, oder Sie können diese Funktion zur Laufzeit mithilfe von JavaScript hinzufügen. Im folgenden Beispiel wird veranschaulicht, wie Sie die Neuanordnungsfunktion hinzufügen, indem Sie das HTML-Markup für das Steuerelement anpassen.
<!-- 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>
Im nächsten Beispiel ist zu sehen, wie Sie die Neuanordnungsfunktion zur Laufzeit mithilfe von JavaScript einem ListView-Steuerelement hinzufügen.
(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 ...
})();
Nachdem Sie die itemsReorderable-Eigenschaft für das ListView-Steuerelement geändert haben, können Sie das Projekt ausführen (mit F5). Wählen Sie ein Element im ListView-Steuerelement aus, und ziehen Sie es an eine andere Position in demselben ListView-Steuerelement.
Schritt 3: Hinzufügen der Ziehfunktion zu einem ListView-Steuerelement
Auf der Basisebene ist das Hinzufügen der Ziehfunktion zu einem ListView-Steuerelement genauso einfach wie das Hinzufügen einer Neuanordnungsfunktion. Das ListView-Steuerelement enthält eine itemsDraggable-Eigenschaft, die Sie deklarativ im HTML-Code für das Steuerelement festlegen oder zur Laufzeit ändern können.
Im nächsten Beispiel wird veranschaulicht, wie Sie einem ListView-Steuerelement im HTML-Markup für das Steuerelement eine einfache Ziehfunktion hinzufügen.
<!-- 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>
Im nächsten Beispiel ist zu sehen, wie Sie einem ListView-Steuerelement zur Laufzeit mithilfe von JavaScript eine einfache Ziehfunktion hinzufügen.
(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 ...
})();
Nachdem Sie die itemsDraggable-Eigenschaft auf "true" festgelegt haben, können Sie die App ausführen (mit F5). Wählen Sie in der App im ListView-Steuerelement ein Element aus, und ziehen Sie es an eine Position außerhalb des ListView-Steuerelements. Das Element wird auf der App-Oberfläche außerhalb des ListView-Steuerelements dupliziert angezeigt. Wenn Sie die Maustaste loslassen, wird das Element ausgeblendet. Anschließend werden die entsprechenden Drop-Ereignisse ausgelöst.
Wenn Sie mit der zugrunde liegenden Datenquelle eines ListView-Steuerelements interagieren möchten, müssen Sie auch Handler für einige Drag & Drop-Ereignisse des ListView-Steuerelements implementieren. Im folgenden Beispiel wurde dem ListView.itemdragstart-Ereignis sowie den Ereignissen dragover und drop des ItemContainer-Elements ein Handler hinzugefügt.
Wenn Sie diesen Code in Verbindung mit dem vorherigen Beispiel verwenden möchten, fügen Sie diesen Code dem app.onactivated-Ereignishandler hinzu, der in der Datei "default.js" der Vorlage Blank app (js/default.js) definiert ist.
// 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;
}
});
});
Im vorherigen Beispiel wurden die ausgewählten Daten, die aus dem ListView-Steuerelement gezogen wurden, im DataTransfer-Objekt gespeichert, das dem itemdragstart-Ereignis zugeordnet ist. Da beide Handler auf dieselbe Datenquelle zugreifen können, wird nur der Index des ausgewählten Elements gespeichert. Andernfalls wäre es möglich, das Objekt als Zeichenfolge im JSON-Format im DataTransfer-Objekt zu serialisieren.
Im Handler für das dragover-Ereignis des ItemContainer-Elements wird das Standardverhalten unterdrückt (beim Standardverhalten ist das Ablegen eines Elements auf einem anderen Element unzulässig). Im drop-Ereignishandler für das ItemContainer-Objekt wird der Index des aus der Datenquelle ausgewählten Elements aus dem DataTransfer-Objekt extrahiert, und anschließend wird das Element aus der Datenquelle des ListView-Steuerelements abgerufen. Im letzten Schritt wird der HTML-Code des ItemContainer-Elements mit den neuen Daten aktualisiert.
Hinweis Wenn von der App Elemente neu angeordnet oder per Drag & Drop in einem gruppierten ListView-Steuerelement zwischen Gruppen abgelegt werden, müssen Sie Elemente aus der Datenquelle entfernen und dann in die neue Gruppe einfügen. Für diesen Vorgang können Sie moveAfter, moveBefore oder moveToStart nicht nutzen.
Schritt 4: Hinzufügen der Ablegefunktion zu einem ListView-Steuerelement
Das Hinzufügen der Ablegefunktion zu einem ListView-Steuerelement ähnelt dem Hinzufügen der Ablegefunktion zum ItemContainer-Steuerelement im vorherigen Beispiel.
Verwenden Sie das folgende Codebeispiel, um das Ablegen von Daten aus dem ItemContainer-Element im ListView-Steuerelement zu ermöglichen.
Wenn Sie diesen Code in Verbindung mit dem vorherigen Beispiel verwenden möchten, fügen Sie diesen Code dem app.onactivated-Ereignishandler hinzu, der in der Datei "default.js" der Vorlage Blank app (js/default.js) definiert ist.
// 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));
});
Im vorherigen Codebeispiel wird dem dragstart-Ereignis des ItemContainer-Elements sowie den Ereignissen itemdragenter und itemdragdrop des ListView-Steuerelements ein Ereignishandler hinzugefügt. Der Handler für das ItemContainer.dragstart -Ereignis extrahiert die Daten aus dem ItemContainer-Element und speichert sie in dem DataTransfer-Objekt, das dem Ereignis zugeordnet ist, als Zeichenfolge im JSON-Format. Im ListView.onitemdragenter-Ereignishandler wird das Standardverhalten des Ereignisses unterdrückt, um das Ablegen der HTML-Inhalte im ListView-Steuerelement zu ermöglichen. Wenn das ListView.onitemdragdrop-Ereignis ausgelöst wird, werden die Daten dann aus dem DataTransfer-Objekt extrahiert und anschließend in die Datenquelle des ListView-Steuerelements eingefügt.
Hinweis Wenn Benutzer versuchen, ein ListView-Steuerelement über die Tastatur neu anzuordnen, ist das DataTransfer-Objekt, das als Argument an das itemdragdrop-Ereignis übergeben wird, nicht definiert. Im Handler für das itemdragdrop-Ereignis müssen Sie sicherstellen, dass das DataTransfer-Objekt vorhanden ist, bevor Sie versuchen, die darin enthaltenen Daten zu lesen.
Anmerkungen
Weitere Informationen zur Verwendung von ListView-Steuerelementen und zum Ermöglichen des Neuanordnens, Ziehens und Ablegens in ListView-Steuerelementen finden Sie unter HTML-ListView-Beispiel für Drag & Drop und Neuanordnung.