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
0會員
1內容數
留言
avatar-img
留言分享你的想法!

































































你可能也想看
Google News 追蹤
- 美國股市 13F 報告顯示,主要對沖基金與投資大佬減持科技股,轉向實業股與 ETF,市場風向可能轉變。 - 0050 迎來分割潮,預計流動性大增,吸引更多散戶與機構資金湧入。 - 巴菲特持倉趨於保守,現金水位仍在歷史高檔,顯示市場估值仍未達他認可的低點。
- 投資應以 ETF 為核心,分散風險,避免單一市場與個股風險,確保長期穩健投資。 - 美中貿易戰升溫,台灣或成美國關稅制裁對象,半導體產業需關注政策變數與台積電的長期競爭力。 - 美股仍在懷疑中成長,即便利空頻傳,標普 500 逼近歷史新高,市場資金流向科技股、黃金與軟性商品。
- 美股持股全面噴發,但台股表現明顯落後,市場偏好不同導致績效差異,供需變化才是投資核心。 - Intel 可能與台積電合作,美國推動晶片回流,短線利好 Intel,長線仍須關注台積電策略。 - 蘋果 AI 轉型與摺疊機市場潛力受關注,市場提前反應新技術趨勢,應留意長期發展與資金流向。
Thumbnail
最近在調整家裡風水,想說反正都整理了乾脆分享出來🤗第一張圖是根據徐玉蘭老師在知識衛星的風水課整理出來的表...
Thumbnail
ListViewItem 交換順序以及拖曳效果。
- 美國股市 13F 報告顯示,主要對沖基金與投資大佬減持科技股,轉向實業股與 ETF,市場風向可能轉變。 - 0050 迎來分割潮,預計流動性大增,吸引更多散戶與機構資金湧入。 - 巴菲特持倉趨於保守,現金水位仍在歷史高檔,顯示市場估值仍未達他認可的低點。
- 投資應以 ETF 為核心,分散風險,避免單一市場與個股風險,確保長期穩健投資。 - 美中貿易戰升溫,台灣或成美國關稅制裁對象,半導體產業需關注政策變數與台積電的長期競爭力。 - 美股仍在懷疑中成長,即便利空頻傳,標普 500 逼近歷史新高,市場資金流向科技股、黃金與軟性商品。
- 美股持股全面噴發,但台股表現明顯落後,市場偏好不同導致績效差異,供需變化才是投資核心。 - Intel 可能與台積電合作,美國推動晶片回流,短線利好 Intel,長線仍須關注台積電策略。 - 蘋果 AI 轉型與摺疊機市場潛力受關注,市場提前反應新技術趨勢,應留意長期發展與資金流向。
Thumbnail
最近在調整家裡風水,想說反正都整理了乾脆分享出來🤗第一張圖是根據徐玉蘭老師在知識衛星的風水課整理出來的表...
Thumbnail
ListViewItem 交換順序以及拖曳效果。