WPF 筆記 | Adorner ListView舉例

更新 發佈閱讀 16 分鐘

成果

成果展示

成果展示

應用需求

使用者在操作時提示給使用者會插入的位置。


實作

1.建立控制元件ListView

使用使用到拖曳需要將Drop的功能開啟。

<ListView 
AllowDrop="True"
MouseMove="ListView_MouseMove"
DragDrop.Drop="ListView_Drop"
DragDrop.DragOver="ListView_DragOver">
<ListViewItem Content="Item1" Padding="0 10"/>
<ListViewItem Content="Item2" Padding="0 10"/>
<ListViewItem Content="Item3" Padding="0 10"/>
<ListViewItem Content="Item4" Padding="0 10"/>
</ListView>

2.實作 DragListViewItemAdorner

重新覆寫(override)繪製方法,在需要插入的位置的地方繪製一條線提示使用者。

/// <summary>
/// 拖曳ListViewItem時產生的繪圖
/// </summary>
public class DragListViewItemAdorner : Adorner
{
/// <summary>
/// 插入此元件的上面或下面位置
/// </summary>
public AlignmentY DragAlign = AlignmentY.Bottom;

public DragListViewItemAdorner(UIElement adornedElement) : base(adornedElement) { }
public DragListViewItemAdorner(UIElement adornedElement, AlignmentY align) : base(adornedElement)
{
DragAlign = align;
}
protected override void OnRender(DrawingContext drawingContext)
{
Rect adornedElementRect = new Rect(this.AdornedElement.RenderSize);
Pen renderPen = new Pen(new SolidColorBrush(Colors.Navy), 1.5);
if (DragAlign == AlignmentY.Bottom)
drawingContext.DrawLine(renderPen, adornedElementRect.BottomLeft, adornedElementRect.BottomRight);
else if (DragAlign == AlignmentY.Top)
drawingContext.DrawLine(renderPen, adornedElementRect.TopLeft, adornedElementRect.TopRight);
}
}

3.拖曳定義

設定拖曳的是ListViewItem時才會有效果。

private void ListView_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
if (sender is ListView LVControl && LVControl.SelectedItem != null)
{
DragDrop.DoDragDrop(LVControl, LVControl.SelectedItem, DragDropEffects.Move);
}
}
}

4.拖曳時的事件

鼠標移動時偵測是否停留在ListViewItem上若不是則會改變鼠標圖示,若停留在ListViewItem上則會判斷該插入的是此ListViewItem的上面或下面位置。

private void ListView_DragOver(object sender, DragEventArgs e)
{ Point currentPosition;
AlignmentY alignY;
e.Effects = DragDropEffects.None;

if (e.Data.GetData(typeof(ListViewItem)) is ListViewItem el)
{
if ( e.Source is ListViewItem selectItem)
{
currentPosition = e.GetPosition(selectItem);
alignY = currentPosition.Y > (selectItem.ActualHeight / 2) ? AlignmentY.Bottom : AlignmentY.Top;
e.Effects = DragDropEffects.Move;
SetElementAdorner(selectItem, alignY);
}
else
{
RemoveElementAdorner();
}
}
}

5.拖曳完成事件

檢查選取的Item與插入的item是否不同,則會判斷該插入的位置進行插入。

private void ListView_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetData(typeof(ListViewItem)) is ListViewItem el)
{
if( e.Source is ListViewItem selectItem)
{
ListView lvControl = (ListView)sender;
if (selectItem != el)
{
// 改變控建順序
AlignmentY alignY;
int i1, i2, diff;
i1 = lvControl.Items.IndexOf(el);
i2 = lvControl.Items.IndexOf(selectItem);
alignY = GetElementAdornerAlignmentY(el);
if(alignY != AlignmentY.Center)
{
diff = i2 > i1 ? 1 : -1;
if (i1 >= 0 && i2 >= 0)
{
ListViewItem item1;
item1 = (ListViewItem)lvControl.Items[i1];
lvControl.Items.RemoveAt(i1);
if (i2 > i1)
{
if (alignY == AlignmentY.Top)
lvControl.Items.Insert(i2 - 1, item1);
else if (alignY == AlignmentY.Bottom)
lvControl.Items.Insert(i2, item1);
}
else
{
if (alignY == AlignmentY.Top)
lvControl.Items.Insert(i2, item1);
else if (alignY == AlignmentY.Bottom)
lvControl.Items.Insert(i2 + 1, item1);
}
}
}
}
}
RemoveElementAdorner();
}
}

6.Adorner 相關方法

取得目前該插入的位置,設置方法和移除方法。

private UIElement AdornerElement;

/// <summary>
/// 取得 Adorner的插入位置
/// </summary>
private AlignmentY GetElementAdornerAlignmentY(UIElement el)
{
AdornerLayer elAdornerLayer = AdornerLayer.GetAdornerLayer(el);
Adorner[] AdronerLayers = elAdornerLayer.GetAdorners(AdornerElement);
if (AdronerLayers != null)
{
if (AdronerLayers.Length > 0)
if (AdronerLayers[0] is DragListViewItemAdorner adornerly)
return adornerly.DragAlign;
}
return AlignmentY.Center;
}
/// <summary>
/// 設置 Adorner
/// </summary>
private void SetElementAdorner(UIElement el, AlignmentY align)
{
AdornerLayer elAdornerLayer;
if (el == AdornerElement && AdornerElement != null)
{
elAdornerLayer = AdornerLayer.GetAdornerLayer(AdornerElement);
Adorner[] AdronerLayers = elAdornerLayer.GetAdorners(AdornerElement);
if (AdronerLayers != null)
{
AlignmentY aligny = GetElementAdornerAlignmentY(AdornerElement);

if (AdronerLayers.Length > 0)
{
if (AdronerLayers[0] is DragListViewItemAdorner adornerly)
{
if (adornerly.DragAlign != align)
{
adornerly.DragAlign = align;
adornerly.InvalidateVisual();
}
}
}
}
}
else
{
if (AdornerElement != null)
RemoveElementAdorner();
AdornerElement = el;

elAdornerLayer = AdornerLayer.GetAdornerLayer(AdornerElement);
if (elAdornerLayer != null)
elAdornerLayer.Add(new DragListViewItemAdorner(AdornerElement, align));
}
}
/// <summary>
/// 移除 Adorner
/// </summary>
private void RemoveElementAdorner()
{
if( AdornerElement != null)
{
AdornerLayer elAdornerLayer = AdornerLayer.GetAdornerLayer(AdornerElement);
Adorner[] AdronerLayers = elAdornerLayer.GetAdorners(AdornerElement);
if (AdronerLayers != null)
{
for (int i = 0; i < AdronerLayers.Length; i++)
elAdornerLayer.Remove(AdronerLayers[i]);
}
AdornerElement = null;
}
}




留言
avatar-img
Wuill的沙龍
0會員
2內容數
你可能也想看
Thumbnail
5 月,方格創作島正式開島。這是一趟 28 天的創作旅程。活動期間,每週都會有新的任務地圖與陪跑計畫,從最簡單的帳號使用、沙龍建立,到帶著你從一句話、一張照片開始,一步一步找到屬於自己的創作節奏。不需要長篇大論,不需要完美的文筆,只需要帶上你今天的日常,就可以出發。征服創作島,抱回靈感與大獎!
Thumbnail
5 月,方格創作島正式開島。這是一趟 28 天的創作旅程。活動期間,每週都會有新的任務地圖與陪跑計畫,從最簡單的帳號使用、沙龍建立,到帶著你從一句話、一張照片開始,一步一步找到屬於自己的創作節奏。不需要長篇大論,不需要完美的文筆,只需要帶上你今天的日常,就可以出發。征服創作島,抱回靈感與大獎!
Thumbnail
當時間變少之後,看戲反而變得更加重要——這是在成為母親之後,我第一次誠實地面對這一件事:我沒有那麼多的晚上,可以任性地留給自己了。看戲不再只是「今天有沒有空」,而是牽動整個週末的結構,誰應該照顧孩子,我該在什麼時間回到家,隔天還有沒有精神帶小孩⋯⋯於是,我不得不學會一件以前並不擅長的事:挑選。
Thumbnail
當時間變少之後,看戲反而變得更加重要——這是在成為母親之後,我第一次誠實地面對這一件事:我沒有那麼多的晚上,可以任性地留給自己了。看戲不再只是「今天有沒有空」,而是牽動整個週末的結構,誰應該照顧孩子,我該在什麼時間回到家,隔天還有沒有精神帶小孩⋯⋯於是,我不得不學會一件以前並不擅長的事:挑選。
Thumbnail
當代名導基里爾.賽勒布倫尼科夫身兼電影、劇場與歌劇導演,其作品流動著強烈的反叛與詩意。在俄烏戰爭爆發後,他持續以創作回應專制體制的壓迫。《傳奇:帕拉贊諾夫的十段殘篇》致敬蘇聯電影大師帕拉贊諾夫。本文作者透過媒介本質的分析,解構賽勒布倫尼科夫如何利用影劇雙棲的特質,在荒謬世道中尋找藝術的「生存之道」。
Thumbnail
當代名導基里爾.賽勒布倫尼科夫身兼電影、劇場與歌劇導演,其作品流動著強烈的反叛與詩意。在俄烏戰爭爆發後,他持續以創作回應專制體制的壓迫。《傳奇:帕拉贊諾夫的十段殘篇》致敬蘇聯電影大師帕拉贊諾夫。本文作者透過媒介本質的分析,解構賽勒布倫尼科夫如何利用影劇雙棲的特質,在荒謬世道中尋找藝術的「生存之道」。
Thumbnail
高中數學主題練習—根式化簡
Thumbnail
高中數學主題練習—根式化簡
Thumbnail
透明立體方練習,使用AI向量繪圖軟體
Thumbnail
透明立體方練習,使用AI向量繪圖軟體
Thumbnail
見諸參與鄧伯宸口述,鄧湘庭於〈那個大霧的時代〉記述父親回憶,鄧伯宸因故遭受牽連,而案件核心的三人,在鄧伯宸記憶裡:「成立了成大共產黨,他們製作了五星徽章,印刷共產黨宣言——刻鋼板的——他們收集中共空飄的傳單,以及中國共產黨中央委員會有關文化大革命決議文的英文打字稿,另外還有手槍子彈十發。」
Thumbnail
見諸參與鄧伯宸口述,鄧湘庭於〈那個大霧的時代〉記述父親回憶,鄧伯宸因故遭受牽連,而案件核心的三人,在鄧伯宸記憶裡:「成立了成大共產黨,他們製作了五星徽章,印刷共產黨宣言——刻鋼板的——他們收集中共空飄的傳單,以及中國共產黨中央委員會有關文化大革命決議文的英文打字稿,另外還有手槍子彈十發。」
Thumbnail
高中數學主題練習—根式化簡
Thumbnail
高中數學主題練習—根式化簡
Thumbnail
高中數學主題練習—配方法
Thumbnail
高中數學主題練習—配方法
Thumbnail
高中數學主題練習—配方法
Thumbnail
高中數學主題練習—配方法
Thumbnail
在Excel中實作使用者介面(UI)是一個有趣且實用的技能,能夠幫助你更好地呈現資料、提供功能並增強使用者體驗。本文將逐步介紹如何在Excel中建立基本的UI元素,例如按鈕、下拉式選單和文字框,並擴展功能,例如資料驗證和動態更新。
Thumbnail
在Excel中實作使用者介面(UI)是一個有趣且實用的技能,能夠幫助你更好地呈現資料、提供功能並增強使用者體驗。本文將逐步介紹如何在Excel中建立基本的UI元素,例如按鈕、下拉式選單和文字框,並擴展功能,例如資料驗證和動態更新。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News