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;
}
}




0會員
1內容數
留言0
查看全部
發表第一個留言支持創作者!
你可能也想看
Google News 追蹤
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
美國總統大選只剩下三天, 我們觀察一整週民調與金融市場的變化(包含賭局), 到本週五下午3:00前為止, 誰是美國總統幾乎大概可以猜到60-70%的機率, 本篇文章就是以大選結局為主軸來討論近期甚至到未來四年美股可能的改變
从个人发展的角度来讲,我认为每个人都要有一点自己的长处,这个长处并不是人们常说的一些爱好之类的东西,而是个人身上那种相对稀缺的禀赋,或者是几种特质组合起来的独特性能。 这是任何时候都能保持一定竞争力的前提,也是一种不需要卷就能体现出来的个人优势。其实不需要对自己要求很高,只要在自己的领域高于平均,就
Thumbnail
在日常工作、学习、生活中,笔记软件成为重要的生产力工具。然而,如今的笔记软件百花齐放:云文档? 云笔记? 离线笔记? Markdown 编辑器? 块编辑器?双链笔记?在每个类别中,都有几十款比较有名的笔记软件。那么,我们应该如何选择这些适合自己的笔记软件呢? 文本编辑器的特征 文本编辑器的分类
Thumbnail
寧靜可以致遠,淡定之心,真的很不容易維持。海量的信息,每天迎面而來,不使人心生浮躁都難!     如何「心有徵知」?荀子提示了「虛壹而靜」的辦法,真的很不錯。如其不然,持守著信仰也很好。信仰佛法的在家居士、禪和子或許採取的是禪家晏坐的辦法;信靠基督的弟兄姊妹或者用禱告、敬拜、等候神的辦法;至於沒有固
Thumbnail
    古人有云:「生年不滿百,常懷千歲憂。」這是魏晋之交文人的「憂生之嗟」。而今天台灣社會的隱憂,則是悄悄邁入超高齡的社會,「老人照顧更老的」正在成爲普遍的現象。主政者根本無心、無力,也還沒準備好如何去應對,因此整個社會無論老少,心頭都是沉重的。    有位大陸老友,他的豪情是:爲國工作70年。
Thumbnail
兩年多前,開始有了重新架構網站的想法,所以把 Blogger 架設的網站,移轉至到了新的平台,當年我也做過了一些優缺點評析,剛好最近又再重新整理網站的所有架構,順便也重新啟動了一次 Hugo 架設網站的循環。
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
美國總統大選只剩下三天, 我們觀察一整週民調與金融市場的變化(包含賭局), 到本週五下午3:00前為止, 誰是美國總統幾乎大概可以猜到60-70%的機率, 本篇文章就是以大選結局為主軸來討論近期甚至到未來四年美股可能的改變
从个人发展的角度来讲,我认为每个人都要有一点自己的长处,这个长处并不是人们常说的一些爱好之类的东西,而是个人身上那种相对稀缺的禀赋,或者是几种特质组合起来的独特性能。 这是任何时候都能保持一定竞争力的前提,也是一种不需要卷就能体现出来的个人优势。其实不需要对自己要求很高,只要在自己的领域高于平均,就
Thumbnail
在日常工作、学习、生活中,笔记软件成为重要的生产力工具。然而,如今的笔记软件百花齐放:云文档? 云笔记? 离线笔记? Markdown 编辑器? 块编辑器?双链笔记?在每个类别中,都有几十款比较有名的笔记软件。那么,我们应该如何选择这些适合自己的笔记软件呢? 文本编辑器的特征 文本编辑器的分类
Thumbnail
寧靜可以致遠,淡定之心,真的很不容易維持。海量的信息,每天迎面而來,不使人心生浮躁都難!     如何「心有徵知」?荀子提示了「虛壹而靜」的辦法,真的很不錯。如其不然,持守著信仰也很好。信仰佛法的在家居士、禪和子或許採取的是禪家晏坐的辦法;信靠基督的弟兄姊妹或者用禱告、敬拜、等候神的辦法;至於沒有固
Thumbnail
    古人有云:「生年不滿百,常懷千歲憂。」這是魏晋之交文人的「憂生之嗟」。而今天台灣社會的隱憂,則是悄悄邁入超高齡的社會,「老人照顧更老的」正在成爲普遍的現象。主政者根本無心、無力,也還沒準備好如何去應對,因此整個社會無論老少,心頭都是沉重的。    有位大陸老友,他的豪情是:爲國工作70年。
Thumbnail
兩年多前,開始有了重新架構網站的想法,所以把 Blogger 架設的網站,移轉至到了新的平台,當年我也做過了一些優缺點評析,剛好最近又再重新整理網站的所有架構,順便也重新啟動了一次 Hugo 架設網站的循環。