@dotnet/
使用 Blazor
Blazor 的 GitHub 存儲庫包含可排序列表的源代碼以及演示。對于您自己的項目,您只需要 Shared/.razor、Shared/.razor.css 和 Shared/.razor.js 文件。
組件是一個通用組件,它采用項目列表和定義如何呈現可排序列表中每個項目的 。例如,假設您有一個如下所示的書籍列表......
public class Book
{
? ?public string Title { get; set; } = "";
? ?public string Author { get; set; } ?= "";
? ?public int Year { get; set; }
}
public List
books = new List {
? ?new Book { Title = "The Very Hungry Caterpillar", Author = "Eric Carle", Year = 1969 },
? ?new Book { Title = "Where the Wild Things Are", Author = "Maurice Sendak", Year = 1963 },
? ?new Book { Title = "Goodnight Moon", Author = "Margaret Wise Brown", Year = 1947 },
? ?new Book { Title = "The Cat in the Hat", Author = "Dr. Seuss", Year = 1957 },
? ?new Book { Title = "Charlotte's Web", Author = "E.B. White", Year = 1952 },
? ?new Book { Title = "Harry Potter and the Sorcerer's Stone", Author = "J.K. Rowling", Year = 1997 },
? ?new Book { Title = "The Lion, the Witch and the Wardrobe", Author = "C.S. Lewis", Year = 1950 },
? ?new Book { Title = "Matilda", Author = "Roald Dahl", Year = 1988 },
? ?new Book { Title = "The Giving Tree", Author = "Shel Silverstein", Year = 1964 },
? ?new Book { Title = "Oh, the Places You'll Go!", Author = "Dr. Seuss", Year = 1990 }
};
您可以在 中像下面這樣呈現此列表......
? ?"books" Context="book">
? ? ? ?
? ? ? ? ? ?class="book"> ? ? ? ? ? ? ? ?@book.Title
? ? ? ? ? ?
? ? ? ?
? ?
組件將使用 呈現項目列表,然后使用 使列表變得可以排序。Context 參數用于定義變量的名稱,該變量將用于表示列表中的每個項目。在本例中,Context 是 book,因此列表中的每個項目都將由一個名為 book 的變量表示。
但是,如果您此時嘗試拖放項目,您會發現無論您怎么拖放一個項目,它都會回到之前的位置。這是因為我們沒有告訴 在列表排序時該做什么。我們通過處理 事件并自己進行排序來做到這一點。
? ?
"books" Context="book" OnUpdate="@SortList">? ? ? ?
? ? ? ? ? ?
class="book">? ? ? ? ? ? ? ?
@book.Title
? ? ? ? ? ?
? ? ? ?
? ?
...
public void SortList((int oldIndex, int newIndex) indices)
{
? ?// deconstruct the tuple
? ?var (oldIndex, newIndex) = indices;
? ?var items = this.books;
? ?var itemToMove = items[oldIndex];
? ?items.RemoveAt(oldIndex);
? ?if (newIndex < items.Count)
? ?{{
? ? ? ?items.Insert(newIndex, itemToMove);
? ?}}
? ?else
? ?{{
? ? ? ?items.Add(itemToMove);
? ?}}
}
每當列表排序時,都會調用 事件處理程序。它將傳遞一個包含已移動項目的舊索引和新索引的元組。在 方法中,我們將元組解構為兩個變量,然后使用它們來移動列表中的項目。
永遠不要改變 Blazor 控制的 DOM,這一點非常重要。Blazor 保留 DOM 的內部副本,如果您使用 等內容更改它,您將得到奇怪的結果,因為頁面狀態將與 Blazor 的內部狀態不同步。因此,我們在幕后所做的就是取消 移動,這樣被移動的項目就不會真的在頁面上移動。然后我們移動列表中的項目,Blazor 將按照新順序重新渲染列表。
一個更復雜的例子
是一個非常強大的庫,它可以做的不僅僅是排序列表。它還可以在列表之間排序、克隆項目、過濾項目等等。 組件支持許多這樣的功能。讓我們看一個更復雜的例子——兩個列表之間的排序......
? ?class="container"> ? ? ? ?class="columns"> ? ? ? ? ? ?class="column"> ? ? ? ? ? ? ? ?Books
? ? ? ? ? ? ? ?"books" Context="book" OnRemove="@AddToFavoriteList" Group="favorites">
? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ?class="book"> ? ? ? ? ? ? ? ? ? ? ? ? ? ?@book.Title
? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ?
? ? ? ? ? ?
? ? ? ? ? ?class="column"> ? ? ? ? ? ? ? ?Favorite Books
? ? ? ? ? ? ? ?"favoriteBooks" Context="book" OnRemove="@RemoveFromFavoriteList" Group="favorites">
? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ?class="book"> ? ? ? ? ? ? ? ? ? ? ? ? ? ?@book.Title
? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ?
? ? ? ? ? ?
? ? ? ?
? ?
在此示例中,我們有兩個列表 - 所有書籍的列表和最喜歡的書籍的列表。它們通過 Group 屬性鏈接在一起。
我們希望能夠將書籍從所有書籍列表拖放到最喜歡的書籍列表中。要做到這一點,我們需要處理兩個列表的 事件。
public void AddToFavoriteList((int oldIndex, int newIndex) indices)
{
? ?var (oldIndex, newIndex) = indices;
? ?var book = books[oldIndex];
? ?favoriteBooks.Insert(newIndex, book);
? ?books.RemoveAt(oldIndex);
}
public void RemoveFromFavoriteList((int oldIndex, int newIndex) indices)
{
? ?var (oldIndex, newIndex) = indices;
? ?var book = favoriteBooks[oldIndex];
? ?books.Insert(newIndex, book);
? ?favoriteBooks.RemoveAt(oldIndex);
}
設置 的樣式
默認情況下, 包含一些默認樣式,這些樣式在拖動時會隱藏“ghost”元素。這將在您拖動時在項目之間產生間隙。如果沒有這種樣式更改,項目本身將顯示為可放置拖動項目的目標。這有點奇怪,因為這意味著您拖動的項目也是您放置拖動項目的目的地。但如果這就是您想要選的樣式,您可以覆蓋 .razor.css 文件中的樣式,或者根本不包含它。
由于 內呈現的所有內容都呈現在 子項內,因此您必須使用“::deep”修飾符才能使任何更改生效。
如果您從父頁面/組件(即 Index.razor.css)設置 的樣式,則必須將 包裝在容器元素中,并使用“::deep”修飾符。如果您不這樣做,您的樣式將不會生效,您也會因為我制作這個組件卻沒有這個功能而感到悲傷、困惑和生氣。這是 Blazor 的問題,而不是 的問題。您可以在 ASP.NET Core 文檔中閱讀有關范圍樣式的更多信息。
我覺得沒有人會讀最后一段,很多人可能會哀號。我先說聲抱歉,但其實我已經嘗試過了。
ASP.NET Core 文檔
#child--support
為什么不使用 HTML5 拖放?
這是一個很好的問題,也是我在使用 解決方案之前研究過的一個問題。總而言之,原生 HTML5 對拖放的支持還不夠強大,無法實現合適的排序。例如,無法對大部分拖放行為進行樣式化。它看起來……很愚蠢……而且我們對此無能為力。它對跨瀏覽器的支持也很不穩定。有一些基本屬性僅適用于 Chrome。
綜上所述, 實際上會嘗試使用 HTML5 拖放,并在 iOS 等平臺上退回到 解決方案。但是,您仍然無法控制樣式,并且會出現看起來愚蠢的拖放操作。所以我在 上關閉了 HTML5 的方式。如果您希望它重新打開,請進入 .razor.razor.js 文件并刪除 : true 屬性。我可能會在某個時候將其作為一個設置。
支持也很不穩定
獲取 Blazor
查看 Blazor 并告訴我們您的想法!您可以用它做很多事情,包括克隆項目、禁用某些項目的排序、指定拖動手柄等等。我們還沒有實現 的所有功能。歡迎拉取請求!
Blazor
Blazor 是一個開源社區項目。
微信公眾號|微軟開發者MSDN
新浪微博|微軟中國MSDN
·END·
*請認真填寫需求信息,我們會在24小時內與您取得聯系。