WPF 筆記 | Adorner ListView舉例

更新於 2024/02/19閱讀時間約 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
0會員
1內容數
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
你可能也想看
Google News 追蹤
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
从个人发展的角度来讲,我认为每个人都要有一点自己的长处,这个长处并不是人们常说的一些爱好之类的东西,而是个人身上那种相对稀缺的禀赋,或者是几种特质组合起来的独特性能。 这是任何时候都能保持一定竞争力的前提,也是一种不需要卷就能体现出来的个人优势。其实不需要对自己要求很高,只要在自己的领域高于平均,就
Thumbnail
在日常工作、学习、生活中,笔记软件成为重要的生产力工具。然而,如今的笔记软件百花齐放:云文档? 云笔记? 离线笔记? Markdown 编辑器? 块编辑器?双链笔记?在每个类别中,都有几十款比较有名的笔记软件。那么,我们应该如何选择这些适合自己的笔记软件呢? 文本编辑器的特征 文本编辑器的分类
Thumbnail
寧靜可以致遠,淡定之心,真的很不容易維持。海量的信息,每天迎面而來,不使人心生浮躁都難!     如何「心有徵知」?荀子提示了「虛壹而靜」的辦法,真的很不錯。如其不然,持守著信仰也很好。信仰佛法的在家居士、禪和子或許採取的是禪家晏坐的辦法;信靠基督的弟兄姊妹或者用禱告、敬拜、等候神的辦法;至於沒有固
Thumbnail
    古人有云:「生年不滿百,常懷千歲憂。」這是魏晋之交文人的「憂生之嗟」。而今天台灣社會的隱憂,則是悄悄邁入超高齡的社會,「老人照顧更老的」正在成爲普遍的現象。主政者根本無心、無力,也還沒準備好如何去應對,因此整個社會無論老少,心頭都是沉重的。    有位大陸老友,他的豪情是:爲國工作70年。
Thumbnail
兩年多前,開始有了重新架構網站的想法,所以把 Blogger 架設的網站,移轉至到了新的平台,當年我也做過了一些優缺點評析,剛好最近又再重新整理網站的所有架構,順便也重新啟動了一次 Hugo 架設網站的循環。
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
从个人发展的角度来讲,我认为每个人都要有一点自己的长处,这个长处并不是人们常说的一些爱好之类的东西,而是个人身上那种相对稀缺的禀赋,或者是几种特质组合起来的独特性能。 这是任何时候都能保持一定竞争力的前提,也是一种不需要卷就能体现出来的个人优势。其实不需要对自己要求很高,只要在自己的领域高于平均,就
Thumbnail
在日常工作、学习、生活中,笔记软件成为重要的生产力工具。然而,如今的笔记软件百花齐放:云文档? 云笔记? 离线笔记? Markdown 编辑器? 块编辑器?双链笔记?在每个类别中,都有几十款比较有名的笔记软件。那么,我们应该如何选择这些适合自己的笔记软件呢? 文本编辑器的特征 文本编辑器的分类
Thumbnail
寧靜可以致遠,淡定之心,真的很不容易維持。海量的信息,每天迎面而來,不使人心生浮躁都難!     如何「心有徵知」?荀子提示了「虛壹而靜」的辦法,真的很不錯。如其不然,持守著信仰也很好。信仰佛法的在家居士、禪和子或許採取的是禪家晏坐的辦法;信靠基督的弟兄姊妹或者用禱告、敬拜、等候神的辦法;至於沒有固
Thumbnail
    古人有云:「生年不滿百,常懷千歲憂。」這是魏晋之交文人的「憂生之嗟」。而今天台灣社會的隱憂,則是悄悄邁入超高齡的社會,「老人照顧更老的」正在成爲普遍的現象。主政者根本無心、無力,也還沒準備好如何去應對,因此整個社會無論老少,心頭都是沉重的。    有位大陸老友,他的豪情是:爲國工作70年。
Thumbnail
兩年多前,開始有了重新架構網站的想法,所以把 Blogger 架設的網站,移轉至到了新的平台,當年我也做過了一些優缺點評析,剛好最近又再重新整理網站的所有架構,順便也重新啟動了一次 Hugo 架設網站的循環。