Wpf DataGrid插入列,列的类型问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Wpf DataGrid插入列,列的类型问题相关的知识,希望对你有一定的参考价值。
在C# winform窗口程序中 DataGird插入列允许有按钮 或者图片类型的列。
wpf程序中默认是没有的,请问wpf的DataGird可以插入 按钮列 和图片列吗?
如果可以,要怎么操作呢?
按钮列:
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Click="Button_Click" Tag="Binding Id"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
图片列:
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image Source="Binding ImageSource"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
我给这些列加了绑定的属性,也可以不加!~望对你有帮助^ ^ 参考技术A 重DataGridTextBoxColumn类
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Data;
using System.Collections;
namespace ImageCellInDataGrid
/// <summary>
/// Summary description for DataGridImageCell.
/// </summary>
public class DataGridImageCell : DataGridTextBoxColumn
private ArrayList theImages1;
public DataGridImageCell()
public ArrayList theImages
getreturn theImages1;
settheImages1 = value;
protected override void Paint(System.Drawing.Graphics g, System.Drawing.Rectangle bounds, System.Windows.Forms.CurrencyManager source, int rowNum, System.Drawing.Brush backBrush, System.Drawing.Brush foreBrush, bool alignToRight)
object o = this.GetColumnValueAtRow(source, rowNum);
if(o != null)
int i = (int)o;
g.FillRectangle(backBrush, bounds);
Bitmap bmp = (Bitmap)theImages[i];
//GridImageCellDrawOption cellDrawOption = GridImageCellDrawOption.NoResize;
//GridImageCellDrawOption cellDrawOption = GridImageCellDrawOption.FitProportionally;
GridImageCellDrawOption cellDrawOption = GridImageCellDrawOption.FitToCell;
System.Drawing.GraphicsUnit gu = System.Drawing.GraphicsUnit.Point;
RectangleF srcRect = bmp.GetBounds(ref gu);
Rectangle destRect = Rectangle.Empty;
Region saveRegion = g.Clip;
switch(cellDrawOption)
case GridImageCellDrawOption.FitToCell:
destRect = bounds;
break;
case GridImageCellDrawOption.NoResize:
destRect = new Rectangle(bounds.X, bounds.Y, (int) srcRect.Width, (int) srcRect.Height);
g.Clip = new Region(bounds);
break;
case GridImageCellDrawOption.FitProportionally:
float srcRatio = srcRect.Width / srcRect.Height;
float tarRatio = (float) bounds.Width / bounds.Height;
destRect = bounds;
if( tarRatio < srcRatio )
destRect.Height = (int) (destRect.Width * srcRatio);
else
destRect.Width = (int) (destRect.Height * srcRatio);
break;
default:
break;
if(!destRect.IsEmpty)
g.DrawImage(bmp, destRect, srcRect, gu);
g.Clip = saveRegion;
protected override void Edit(System.Windows.Forms.CurrencyManager source, int rowNum, System.Drawing.Rectangle bounds, bool readOnly, string instantText, bool cellIsVisible)
//overridden to avoid editing
public enum GridImageCellDrawOption
FitToCell = 0,
NoResize = 1,
FitProportionally = 2,
;
测试代码
private System.Windows.Forms.DataGrid dataGrid1;
private void Form1_Load(object sender, System.EventArgs e)
//create a datatable
DataTable dt = new DataTable("MyTable");
dt.Columns.Add(new DataColumn("Col0"));
dt.Columns.Add(new DataColumn("Images",typeof(int)));
Random r = new Random();
for(int i = 0; i < nRows; ++i)
DataRow dr = dt.NewRow();
dr[0] = string.Format("row0", i);
dr[1] = r.Next(4);
dt.Rows.Add(dr);
//store bitmaps in an arraylist
bitMaps = new ArrayList();
System.IO.Stream strm = GetType().Assembly.GetManifestResourceStream("ImageCellInDataGrid.Blue hills.jpg");
bitMaps.Add(new Bitmap(strm));
strm = GetType().Assembly.GetManifestResourceStream("ImageCellInDataGrid.Sunset.jpg");
bitMaps.Add(new Bitmap(strm));
strm = GetType().Assembly.GetManifestResourceStream("ImageCellInDataGrid.Water lilies.jpg");
bitMaps.Add(new Bitmap(strm));
strm = GetType().Assembly.GetManifestResourceStream("ImageCellInDataGrid.Winter.jpg");
bitMaps.Add(new Bitmap(strm));
DataGridTableStyle tableStyle = new DataGridTableStyle();
tableStyle.MappingName = "MyTable";
DataGridTextBoxColumn tbc = new DataGridTextBoxColumn();
tbc.MappingName = "Col0";
tbc.HeaderText = "Column 1";
tbc.Width = 50;
tableStyle.GridColumnStyles.Add(tbc);
int width = this.dataGrid1.ClientSize.Width - tbc.Width - this.dataGrid1.RowHeaderWidth - 4;
DataGridImageCell tbc1 = new DataGridImageCell();
tbc1.MappingName = "Images";
tbc1.HeaderText = "Images";
tbc1.theImages = bitMaps;
tbc1.Width = width;
tableStyle.GridColumnStyles.Add(tbc1);
this.dataGrid1.TableStyles.Add(tableStyle);
this.dataGrid1.DataSource = dt;
dt.DefaultView.AllowNew = false;
Rectangle rect = this.dataGrid1.GetCellBounds(0,0);
topPos = rect.Top;
int height = (this.dataGrid1.ClientSize.Height - topPos - nRows) / nRows;
tableStyle.PreferredRowHeight = height;
this.dataGrid1.DataSource = null;
this.dataGrid1.DataSource = dt;
WPF 中的 Datagrid - 1 列默认排序
【中文标题】WPF 中的 Datagrid - 1 列默认排序【英文标题】:Datagrid in WPF - 1 column default sorted 【发布时间】:2012-02-16 06:55:15 【问题描述】:在 WPF 中,我有一个包含几列的 DataGrid。
默认情况下,我想让它排序为 1,但我就是找不到如何做到这一点。
XAML 中的 DataGrid 如下所示:
<DataGrid x:Name="LibraryView" ItemsSource="Binding Path=Elements[Persons]" IsReadOnly="True" LoadingRow="dg_LoadingRow">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="Binding Path=Element[Name].Value" IsReadOnly="True" />
<DataGridTextColumn Header="Score" Binding="Binding Path=Element[Score].Value" IsReadOnly="True" />
<DataGridTextColumn Header="Date" Binding="Binding Path=Element[Date].Value" IsReadOnly="True" />
</DataGrid.Columns>
</DataGrid>
而它背后的唯一代码是:
public ScoreBoard()
InitializeComponent();
DataSet ds = dweMethods.DecryptAndDeserialize("ScoreData.xml");
XElement TrackList = XElement.Parse(ds.GetXml());
LibraryView.DataContext = TrackList;
我只是找不到如何使其默认按“分数”列排序。
谁能帮我指出正确的方向?
【问题讨论】:
看看 CollectionViewSource。 我已经尝试过这个:ICollectionView view = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource); view.SortDescriptions.Clear(); view.SortDescriptions.Add(new SortDescription("LastName", ListSortDirection.Ascending)); view.Refresh();
但这似乎不适用于我上面的代码,我不知道也不明白我应该怎么做才能让它工作
您是否考虑过对您的 TrackList 子项进行排序?
uuh,问题是,我现在只有 3 周深入 c#,呵呵,所以我还需要学习一些东西。所以也许我没有以正确的方式设置数据网格以便现在能够使用排序?
Darjan 的解决方案成功了吗?对 XElement 进行排序非常简单——看看 XLINQ Sort。
【参考方案1】:
注意:使用 CollectionViewSource 在这些情况下将为您提供更多的权力和控制。 当您学习 WPF 时,我建议您了解如何使用 CollectionViewSource 与其他集合一起解决此问题 Grouping 和 Filtering 等相关问题。
编辑:这可能是由于规范的变化。此答案基于使用 .NET 4.0,我尚未研究此解决方案是否适用于旧版本的框架。
鉴于此 XAML
<DataGrid x:Name="LibraryView" ItemsSource="Binding Path=Elements[Persons]" IsReadOnly="True" LoadingRow="dg_LoadingRow">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="Binding Path=Element[Name].Value" IsReadOnly="True" />
<DataGridTextColumn Header="Score" Binding="Binding Path=Element[Score].Value" IsReadOnly="True" />
<DataGridTextColumn Header="Date" Binding="Binding Path=Element[Date].Value" IsReadOnly="True" />
</DataGrid.Columns>
</DataGrid>
您需要做的就是选择一列并为该列指定排序方向。
<DataGrid x:Name="LibraryView" ItemsSource="Binding Path=Elements[Persons]" IsReadOnly="True" LoadingRow="dg_LoadingRow">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="Binding Path=Element[Name].Value" IsReadOnly="True" />
<DataGridTextColumn Header="Score" Binding="Binding Path=Element[Score].Value" IsReadOnly="True" SortDirection="Ascending" />
<DataGridTextColumn Header="Date" Binding="Binding Path=Element[Date].Value" IsReadOnly="True" />
</DataGrid.Columns>
</DataGrid>
这将默认按升序排列到第二列。
【讨论】:
当DataGridTextColumn
使用MultiBinding
时,这似乎不起作用,即使设置了SortMemberPath
。单击列标题将对其进行排序,但SortDirection
不会。
@Matt 这可能是使用 CollectionViewSource 会产生更好结果的情况
AFAICT SortDirection 只是在标题中设置箭头。
@fadden 出现这种情况的原因有很多。您需要展示一个具体示例来确定排序失败的原因。
这似乎设置了标题排序箭头,但实际上并未对底层集合进行排序。相反,在 CVS 上设置 SortDescriptions 会对集合进行排序,但对标题箭头没有影响。为什么我想要这个的可能用例是什么?为什么 WPF 一定要这么牛逼?【参考方案2】:
我在这里描述了如何按第一列对代码进行排序:Initial DataGrid Sorting
您可以调整代码以按您想要的特定列进行排序,尽管整个方法看起来很混乱。
如果您想在 XAML 中执行此操作...设置 CollectionViewSource.SortDescriptions 可能有效:
<CollectionViewSource x:Key="cvs" Source="StaticResource myItemsSource">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="MyPropertyName" Direction="Ascending"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
但我从未尝试过后者。
【讨论】:
您提供的这个链接 (***.com/questions/8944822/initial-datagrid-sorting/…) 似乎确实有效,但目前只有 1 个缺点。它对第一列进行排序(在方法中说明),但我怎样才能使它对第二列(或另一个)进行排序? 现在通过更改 Columns.First();到列[1]; (谢谢!) 您应该提及所需的命名空间xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
【参考方案3】:
您可以在后面的代码中使用ICollectionView
。
假设您已定义 ObservableCollection<yourPersonClass> Persons
和 Names
是 yourPersonClass 的属性
public ICollectionView View;
View = CollectionViewSource.GetDefaultView(Persons);
View.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
View.Refresh();
【讨论】:
【参考方案4】:如果您想以编程方式执行此操作,可以这样做:
MyDataGrid.ItemsSource = DataContext.RowItems.OrderBy(p => p.Score).ToList();
【讨论】:
以上是关于Wpf DataGrid插入列,列的类型问题的主要内容,如果未能解决你的问题,请参考以下文章
禁用 WPF MVVM 中 DataGrid 中自动生成的列的排序
WPF DataGrid在同一列中的不同控件 - 不正确的绑定