WPF---ListView新增窗格線
要想直接在WPF中給ListView加上橫豎線條,是一件很費勁的事情,不過我們可以通過其他的辦法,來繞過去,具體是什麼辦法呢,就看下面的步驟吧!
1. 建立一個WPF程式
2. 新增一個類檔案,命名為GridLineDecorator.cs,寫入如下內容
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Markup; using System.Windows.Media; using System.Windows.Threading; namespace ListViewWithLines { [ContentProperty("Target")] public class GridLineDecorator : FrameworkElement { private ListView _target; private DrawingVisual _gridLinesVisual = new DrawingVisual(); private GridViewHeaderRowPresenter _headerRowPresenter = null; public GridLineDecorator() { this.AddVisualChild(_gridLinesVisual); this.AddHandler(ScrollViewer.ScrollChangedEvent, new RoutedEventHandler(OnScrollChanged)); } #region GridLineBrush /// <summary> /// GridLineBrush Dependency Property /// </summary> public static readonly DependencyProperty GridLineBrushProperty = DependencyProperty.Register("GridLineBrush", typeof(Brush), typeof(GridLineDecorator), new FrameworkPropertyMetadata(Brushes.LightGray, new PropertyChangedCallback(OnGridLineBrushChanged))); /// <summary> /// Gets or sets the GridLineBrush property. This dependency property /// indicates .... /// </summary> public Brush GridLineBrush { get { return (Brush)GetValue(GridLineBrushProperty); } set { SetValue(GridLineBrushProperty, value); } } /// <summary> /// Handles changes to the GridLineBrush property. /// </summary> private static void OnGridLineBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((GridLineDecorator)d).OnGridLineBrushChanged(e); } /// <summary> /// Provides derived classes an opportunity to handle changes to the GridLineBrush property. /// </summary> protected virtual void OnGridLineBrushChanged(DependencyPropertyChangedEventArgs e) { DrawGridLines(); } #endregion #region Target public ListView Target { get { return _target; } set { if (_target != value) { if (_target != null) Detach(); RemoveVisualChild(_target); RemoveLogicalChild(_target); _target = value; AddVisualChild(_target); AddLogicalChild(_target); if (_target != null) Attach(); InvalidateMeasure(); } } } private void GetGridViewHeaderPresenter() { if (Target == null) { _headerRowPresenter = null; return; } _headerRowPresenter = Target.GetDesendentChild<GridViewHeaderRowPresenter>(); } #endregion #region DrawGridLines private void DrawGridLines() { if (Target == null) return; if (_headerRowPresenter == null) return; var itemCount = Target.Items.Count; if (itemCount == 0) return; var gridView = Target.View as GridView; if (gridView == null) return; // 獲取drawingContext var drawingContext = _gridLinesVisual.RenderOpen(); var startPoint = new Point(0, 0); // 為了對齊到畫素的計算引數,否則就會看到有些線是模糊的 var dpiFactor = this.GetDpiFactor(); var pen = new Pen(this.GridLineBrush, 1 * dpiFactor); var halfPenWidth = pen.Thickness / 2; var guidelines = new GuidelineSet(); // 計算表頭的偏移量和大小 var headerOffset = _headerRowPresenter.TranslatePoint(startPoint, this); var headerSize = _headerRowPresenter.RenderSize; var headerBottomY = headerOffset.Y + headerSize.Height; // 計算ScrollViewer的可視區域大小 var item0 = _target.ItemContainerGenerator.ContainerFromIndex(0); if (item0 == null) return; var scrollViewer = item0.GetAncestor<ScrollViewer>(); if (scrollViewer == null) return; var contentElement = scrollViewer.Content as UIElement; var maxLineX = scrollViewer.ViewportWidth; var maxLineY = headerBottomY + contentElement.RenderSize.Height; var vLineY = 0.0; // 畫橫線 for (int i = 0; i < itemCount; i++) { var item = Target.ItemContainerGenerator.ContainerFromIndex(i) as ListViewItem; if (item != null) { var renderSize = item.RenderSize; var offset = item.TranslatePoint(startPoint, this); var hLineX1 = offset.X; var hLineX2 = offset.X + renderSize.Width; var hLineY = offset.Y + renderSize.Height; vLineY = hLineY; // 小於檢視起始位置的不繪製 if (hLineY <= headerBottomY) continue; // 大於檢視結束位置之後的不繪製 if (hLineY > maxLineY) break; // 如果大於橫向寬度,取橫向寬度 if (hLineX2 > maxLineX) hLineX2 = maxLineX; // 加入參考線,對齊到畫素 guidelines.GuidelinesY.Add(hLineY + halfPenWidth); drawingContext.PushGuidelineSet(guidelines); drawingContext.DrawLine(pen, new Point(hLineX1, hLineY), new Point(hLineX2, hLineY)); drawingContext.Pop(); } } // 畫豎線 var columns = gridView.Columns; var vLineX = headerOffset.X; if (vLineY > maxLineY) vLineY = maxLineY; foreach (var column in columns) { var columnWidth = column.GetColumnWidth(); vLineX += columnWidth; if (vLineX > maxLineX) break; // 加入參考線,對齊到畫素 guidelines.GuidelinesX.Add(vLineX + halfPenWidth); drawingContext.PushGuidelineSet(guidelines); drawingContext.DrawLine(pen, new Point(vLineX, headerBottomY), new Point(vLineX, vLineY)); drawingContext.Pop(); } drawingContext.Close(); } #endregion #region Overrides to show Target and grid lines protected override int VisualChildrenCount { get { return Target == null ? 1 : 2; } } protected override System.Collections.IEnumerator LogicalChildren { get { yield return Target; } } protected override Visual GetVisualChild(int index) { if (index == 0) return _target; if (index == 1) return _gridLinesVisual; throw new IndexOutOfRangeException(string.Format("Index of visual child '{0}' is out of range", index)); } protected override Size MeasureOverride(Size availableSize) { if (Target != null) { Target.Measure(availableSize); return Target.DesiredSize; } return base.MeasureOverride(availableSize); } protected override Size ArrangeOverride(Size finalSize) { if (Target != null) Target.Arrange(new Rect(new Point(0, 0), finalSize)); return base.ArrangeOverride(finalSize); } #endregion #region Handle Events private void Attach() { _target.Loaded += OnTargetLoaded; _target.Unloaded += OnTargetUnloaded; _target.SizeChanged += OnTargetSizeChanged; } private void Detach() { _target.Loaded -= OnTargetLoaded; _target.Unloaded -= OnTargetUnloaded; _target.SizeChanged -= OnTargetSizeChanged; } private void OnTargetLoaded(object sender, RoutedEventArgs e) { if (_headerRowPresenter == null) GetGridViewHeaderPresenter(); DrawGridLines(); } private void OnTargetUnloaded(object sender, RoutedEventArgs e) { DrawGridLines(); } private void OnTargetSizeChanged(object sender, SizeChangedEventArgs e) { DrawGridLines(); } private void OnScrollChanged(object sender, RoutedEventArgs e) { DrawGridLines(); } #endregion } }
3. 新增一個類檔案,命名為GridViewColumnHelper.cs,寫入如下內容
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Windows.Controls; namespace ListViewWithLines { internal static class GridViewColumnHelper { private static PropertyInfo DesiredWidthProperty = typeof(GridViewColumn).GetProperty("DesiredWidth", BindingFlags.NonPublic | BindingFlags.Instance); public static double GetColumnWidth(this GridViewColumn column) { return (double.IsNaN(column.Width)) ? (double)DesiredWidthProperty.GetValue(column, null) : column.Width; } } }
4. 新增一個類檔案,命名為VisualService.cs,寫入如下內容
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Media; using System.Windows; namespace ListViewWithLines { public static class VisualService { public static double GetDpiFactor(this Visual target) { var source = PresentationSource.FromVisual(target); return source == null ? 1.0 : 1 / source.CompositionTarget.TransformToDevice.M11; } public static T GetAncestor<T>(this DependencyObject target) where T : DependencyObject { var parent = VisualTreeHelper.GetParent(target); if (parent is T) return (T)parent; if (parent != null) return parent.GetAncestor<T>(); return null; } public static T GetDesendentChild<T>(this DependencyObject target) where T : DependencyObject { var childCount = VisualTreeHelper.GetChildrenCount(target); if (childCount == 0) return null; for (int i = 0; i < childCount; i++) { var current = VisualTreeHelper.GetChild(target, i); if (current is T) return (T)current; var desendent = current.GetDesendentChild<T>(); if (desendent != null) return desendent; } return null; } } }
5. 在介面主XAML檔案中,加入以下內容
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="TreeViewDesign.MainWindow"
xmlns:l="clr-namespace:ListViewWithLines"
x:Name="Window"
Title="開發測試工具"
Width="900" Height="600" Background="White" WindowState="Maximized">
<Grid>
<l:GridLineDecorator GridLineBrush="{Binding ElementName=cb_GridLineBrush, Path=SelectedItem.Content}">
<ListView Background="White" FocusVisualStyle="{x:Null}" Name="FileInfo">
<ListView.View>
<GridView>
<GridViewColumn Header="工程路徑" Width="600" DisplayMemberBinding="{Binding [email protected]}"/>
<GridViewColumn Header="修改日期" Width="200" DisplayMemberBinding="{Binding [email protected]}"/>
</GridView>
</ListView.View>
<ListView.ContextMenu>
<ContextMenu Name="ContextMenu">
<MenuItem Header="建立工程" />
<MenuItem Header="新增工程" />
<MenuItem Header="開啟工程" />
<MenuItem Header="刪除工程" />
</ContextMenu>
</ListView.ContextMenu>
</ListView>
</l:GridLineDecorator>
</Grid>
</window>
6. 在介面主XAML檔案對應的cs檔案的建構函式中,加入以下內容
public MainWindow()
{
this.InitializeComponent();
// 在此點下面插入建立物件所需的程式碼。
string xmlpath = Directory.GetCurrentDirectory() + "\\context.xml";
XmlDocument xml = new XmlDocument();
xml.Load(xmlpath);
XmlDataProvider xdp = new XmlDataProvider();
xdp.Document = xml;
xdp.XPath = @"/Context/URInfo";
this.FileInfo.DataContext = xdp;
this.FileInfo.SetBinding(ComboBox.ItemsSourceProperty, new Binding());
}
7. 自己建立一個xml檔案,裡面填上相應的資料(有幾列就寫幾列)
8. 編譯WPF程式,大功告成了!
相關推薦
WPF---ListView新增窗格線
要想直接在WPF中給ListView加上橫豎線條,是一件很費勁的事情,不過我們可以通過其他的辦法,來繞過去,具體是什麼辦法呢,就看下面的步驟吧! 1. 建立一個WPF程式 2. 新增一個類檔案,命名為GridLineDecorator.cs,寫入如下內容 using Sys
[.Net碼農][WPF] ListView 中 View 的模板替換(新增/刪除列)
===================================================== 今天在網上閒逛,突然發現這邊文章竟然被人毫不尊重原作者權益而胡亂轉載,讓人氣憤。 本著知識共享的目的,歡迎大家轉載,但是轉載請保留本文的原始連結,謝謝! 本文原作者:YuanHui =====
WPF ListView 使用GridView 帶有Header 以及點擊header排序 sort
iou form iss double ase summary emp header descend ListView: <ListView x:Name="lvFiles" VerticalAlignment="Stretch" Backgro
WPF ListView 分組 Grouping
containe card mage dock mod route head nts row 在Resource裏定義數據源和分組字段: <CollectionViewSource x:Key="listData" Source="{Binding Category
【轉】編寫高質量代碼改善C#程序的157個建議——建議87:區分WPF和WinForm的線程模型
ons 拋出異常 ui線程 擴展方法 區分 cli inner 編寫 查看 建議87:區分WPF和WinForm的線程模型WPF和WinForm窗體應用程序都有一個要求,那就是UI元素(如Button、TextBox等)必須由創建它的那個線程進行更新。WinForm在這
WPF ListView 居中顯示
lte sha tty detail lan listview property target article 原文:WPF ListView 居中顯示 今天遇到的問題:
【unity】NavMesh 執行時動態新增 OffMeshLink 線。
遊戲裡 有一些場景內的傳送陣, 做尋路時, 之前要美術預埋 OffMeshLink線。 但策劃會換位置, 兩邊就不一致了。 想著 OffMeshLink好像可以動態加。 網上沒有相關資料, 試了一下是可以的。 編輯器下可以動態加, 程式裡也基本可以
COCOS 3.0 ListView新增條目數
首先建立ListView的layer層,再建立單獨項的Node.csb;然後 在Layer層傳入資料呼叫,通過insertCustomItem()插入每條資料; //節點的建立 .h #pragma once #include "cocos2d.h" #include "
WPF:ListView 分頁
佈局MainWindow.xaml <ListView Name="list_Reg" ItemsSource="{Binding Source={StaticResource Data}}" Style="{StaticResource ListViewStyle
解決matplotlib.pyplot中X軸刻度小及新增網格線的問題
解決matplotlib.pyplot中X軸刻度小及新增網格線的問題 設定 x 軸的刻度大小,x取值範圍為[1,50),步長為2 plt.xticks(np.arange(1,50,2)) 設定 X 軸的網格線,風格為 點畫線 plt.grid(axis=‘
WPF Listview繫結資料發生改變後前端沒有更新
前端沒有更新的原因: 1.將控制元件與列表繫結 ICMask.ItemsSource = _poppingWordList; 2.在更新繫結資料時 _poppingWordList = newWordList; 因為List是引用,這樣是將_poppingWordList的指向的列表更
Android開發:ListView新增 layoutAnimation 動畫
LayoutAnimation作用於ViewGroup,為ViewGroup指定一個動畫,當它的子元素出場時都按照這個動畫出場。 LayoutAnimation作用於viewgroup有兩種方式: 1. 靜態的使用xml檔案實現。 2. 在程式碼中動態實現。 實
ListView新增simple介面卡,使ListView可以顯示一個ImageView和兩個textview
1.首先在activity_main.xml中建立ListView控制元件 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android
Android之listview新增資料篇
一、ListView: 1、 ListView通常有兩個職責: 1、向佈局填充資料 2、處理選擇點選等操作 2、ListView的建立需要3個元素:
【Markdown】新增分隔線
問題:在 MarkdownPad 2 中新增分隔線,如下圖所示: 處理:在一行中用三個以上的星號(*)、減號(-)、下劃線(_)來建立一個分隔線;除空格外行內不能有其他字元;(除第一個符號的左側最多
WPF —ListView用ItemsSource繫結物件列表
雖然wpf 開發有段時間了,但是對於繫結資料這塊兒,理解的還是不太深入 。 xaml <ListView Canvas.Left="59" Canvas.Top="170" Height="253" Name="listView1" Width="714"
萬能的給 RecyclerView新增邊框線 和 圖片邊框線
/** * Created by 寶寶 on 2017/12/8. */ import android.content.Context; import android.content.res.TypedArray; import android.graphics.Can
ListView新增HeadView後佈局紊亂的問題
今天在做專案時,開發了一個類似聯絡人列表,但要求頂部內容固定、可跟隨ListView滾動的功能,雖然使用給ListView新增HeadView的方法實現了效果,但在開發的過程中,還是遇到
為listView新增選項,使得能和listView一起滑動
LayoutInflater inflater = (layoutInflater)getSystemServer(Context.LAYOUT_INFLATER_SERVICE);//得到inflater物件 View view = inflater.inflater(
一步一步教你寫股票走勢圖——K線圖三(新增均線)
在開篇之前,給大家出個小演算法題,一定要做哦,因為既然你打算看本章節內容了,那麼這個小演算法必須得會的喲! 有一組數,1、2、3……99、100,一共一百個數,假設是ListA,現在將 ListA索引為0、1、2、3、4的數相加