C# WPF中的绑定数据
我正在尝试用c#制作简单的WPF应用程序,我有以下问题: 在我的应用程序中,我使用类“Macierz”来表示和处理BigInteger对象数组。现在我需要使用DataGrid(或者其他更好的方法)以图形方式表示这个数组,我不知道如何将这个DataGrid绑定到我的类。我曾试图通过数据源窗口(VS2013)来实现这一点,但当我将类添加到其中时,我的数组没有显示出来。 下面是我班的一些代码:C# WPF中的绑定数据,c#,wpf,data-binding,wpfdatagrid,C#,Wpf,Data Binding,Wpfdatagrid,我正在尝试用c#制作简单的WPF应用程序,我有以下问题: 在我的应用程序中,我使用类“Macierz”来表示和处理BigInteger对象数组。现在我需要使用DataGrid(或者其他更好的方法)以图形方式表示这个数组,我不知道如何将这个DataGrid绑定到我的类。我曾试图通过数据源窗口(VS2013)来实现这一点,但当我将类添加到其中时,我的数组没有显示出来。 下面是我班的一些代码: public class Macierz { public Macierz(ulong A, ulo
public class Macierz
{
public Macierz(ulong A, ulong B)
{
a = A;
b = B;
M = new BigInteger[A, B];
}
private ulong a, b;
public ulong A
{
get
{
return a;
}
}
public ulong B
{
get
{
return b;
}
}
private BigInteger[,] M;
public BigInteger this[ulong A, ulong B]
{
get
{
return M[A, B];
}
set
{
M[A, B] = value;
}
}
public DataTable ToDataTable()
{
DataTable table = new DataTable();
DataRow tmp;
for (ulong i = 0; i < b; i++)
table.Columns.Add(i.ToString(), typeof(BigInteger));
for (ulong i = 0; i < a; i++)
{
tmp = table.NewRow();
for (ulong j = 0; j < b; j++)
tmp[j.ToString()] = M[i, j];
table.Rows.Add(tmp);
}
return table;
}
我需要用文本框的单元格或类似的东西来表示数组,这样用户就可以轻松地更改特定单元格的值
编辑:
现在,感谢user3148019 answer,我在我的类中添加了此方法:
public class Macierz
{
public Macierz(ulong A, ulong B)
{
a = A;
b = B;
M = new BigInteger[A, B];
}
private ulong a, b;
public ulong A
{
get
{
return a;
}
}
public ulong B
{
get
{
return b;
}
}
private BigInteger[,] M;
public BigInteger this[ulong A, ulong B]
{
get
{
return M[A, B];
}
set
{
M[A, B] = value;
}
}
public DataTable ToDataTable()
{
DataTable table = new DataTable();
DataRow tmp;
for (ulong i = 0; i < b; i++)
table.Columns.Add(i.ToString(), typeof(BigInteger));
for (ulong i = 0; i < a; i++)
{
tmp = table.NewRow();
for (ulong j = 0; j < b; j++)
tmp[j.ToString()] = M[i, j];
table.Rows.Add(tmp);
}
return table;
}
这工作得很好,允许我以简单的方式向用户显示数组,但我现在不知道如何允许用户更改原始数组中的值。我曾试图使用CellEditEnding DataGrid事件,但现在我不知道如何访问、读取和验证用户在特定单元格中的输入,特别是如何获取该单元格的坐标(我可能会以某种方式获取类似于“e.Column.something”或“e.Row.something”的信息,但我不知道如何做到这一点)
Macierz
应派生自DependencyObject
ObservableCollection
而不是简单数组dependencProperty
而不是简单的数据类型DataGrid
的DataContext
设置为所需的Macierz
编辑: 你问的问题非常笼统,为了找到一个好的答案,我建议你试试这个方法,当你掌握了窍门后,再问另一个关于你可能遇到的其他问题的问题。例如,如何将ulong用作ObservableCollection的ListSelector,或者如何将页面添加到ItemsControl,或者如何使用具有动态列数的DataGrid 在我开始之前,我必须说这个答案只适用于小尺寸的Macierz,其中两个维度都是int,对于A*B>10000,它变得非常慢 这里的想法是创建一个
ItemsControl
,它是一种基本类型的容器,用于显示一个可观察集合
:
:集合的源(您绑定到该集合)ItemsSource
:每个项目的模板(如何显示集合中的每个项目,我使用了TextBlock(在边框内),因为它的加载速度比TextBox快)ItemTemplate
:每个项目容器的样式。(ItemContainerStyle
和Grid.Row
必须按照此成员中提供的样式设置。)Grid.Column
:项目控制面板的模板。(我使用了具有动态行数和列数的ItemsPanel
,并使用了网格
)GridHelper
行索引
和列索引
,以便每个元素都知道它在网格中所属的位置
这是MainWindow.xaml.cs:
private void PokazButton_Click(object sender, RoutedEventArgs e)
{
this.Cursor = Cursors.Wait;
if (czyCala.IsChecked == true)
GridTabela = M.ToDataTable(0, M.A, 0, M.B);
else
GridTabela = M.ToDataTable(VA, VACount, VB, VBCount);
TabelaDataGrid.DataContext = this;
TabelaDataGrid.ItemsSource = GridTabela.DefaultView;
this.Cursor = null;
}
InitializeComponent();
var mac = new Macierz(100,40);
//fill with test data
for (int i = 0; i < mac.A; i++)
{
for (int j = 0; j < mac.B; j++)
{
mac[i, j].Data = string.Format("{0}...{1}", i, j);
}
}
//set DataContext
this.DataContext = mac;
您还需要一个助手类。这是GridHelper的简化版本。您可以在的中找到原始类:
公共类GridHelper
{
#区域行计数属性
///
///将指定数量的行添加到行定义中。
///默认高度为“自动”
///
公共静态只读DependencyProperty RowCountProperty=
DependencyProperty.RegisterAttached(
“行计数”、typeof(int)、typeof(GridHelper),
新属性元数据(-1,RowCountChanged));
//得到
公共静态int GetRowCount(DependencyObject obj)
{
返回(int)对象GetValue(RowCountProperty);
}
//设置
公共静态void SetRowCount(DependencyObject对象,int值)
{
对象设置值(RowCountProperty,value);
}
//更改事件-添加行
公共静态无效行数已更改(
DependencyObject对象,DependencyPropertyChangedEventArgs e)
{
如果(!(对象是网格)| |(int)e.NewValue<0)
回来
网格网格=(网格)obj;
grid.RowDefinitions.Clear();
对于(int i=0;i<(int)e.NewValue;i++)
grid.RowDefinitions.Add(
新建行定义(){Height=GridLength.Auto});
//设置箭头(网格);
}
#端区
#区域列计数属性
///
///将指定数量的列添加到ColumnDefinitions。
///默认宽度为“自动”
///
公共静态只读DependencyProperty ColumnCountProperty=
DependencyProperty.RegisterAttached(
“ColumnCount”、typeof(int)、typeof(GridHelper),
新属性元数据(-1,ColumnCountChanged));
//得到
公共静态整型GetColumnCount(DependencyObject obj)
{
返回(int)对象GetValue(ColumnCountProperty);
}
//设置
公共静态void SetColumnCount(DependencyObject对象,int值)
{
对象设置值(ColumnCountProperty,value);
}
//更改事件-添加列
公共静态无效列数已更改(
DependencyObject对象,DependencyPropertyChangedEventArgs e)
{
如果(!(对象是网格)| |(int)e.NewValue<0)
回来
网格网格=(网格)obj;
grid.ColumnDefinitions.Clear();
对于(int i=0;i<(int)e.NewValue;i++)
grid.ColumnDefinitions.Add(
新ColumnDefinition(){Width=GridLength.Auto});
//柱(网格);
}
#端区
}
如果没有额外的工作,阵列无法绑定到DataGrid。一种快速解决方案是使用DataTable而不是多维数组:
<Window x:Class="StackExchange.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid AutoGenerateColumns="True" Name="myGrid"/>
</Grid>
我将类更改为从DependencyObject派生,但我不知道下一步该做什么。我应该用l替换我的数组吗
public class Macierz : DependencyObject
{
public Macierz(int A, int B)
{
this.A = A;
this.B = B;
for (int i = 0; i < A; i++)
{
for (int j = 0; j < B; j++)
{
M.Add(new BigInteger(i, j));
}
}
}
//A Dependency Property
public int A
{
get { return (int)GetValue(AProperty); }
private set { SetValue(AProperty, value); }
}
public static readonly DependencyProperty AProperty =
DependencyProperty.Register("A", typeof(int), typeof(Macierz), new UIPropertyMetadata(0));
//B Dependency Property
public int B
{
get { return (int)GetValue(BProperty); }
private set { SetValue(BProperty, value); }
}
public static readonly DependencyProperty BProperty =
DependencyProperty.Register("B", typeof(int), typeof(Macierz), new UIPropertyMetadata(0));
//Rows Observable Collection
public ObservableCollection<BigInteger> M { get { return _m; } }
private ObservableCollection<BigInteger> _m = new ObservableCollection<BigInteger>();
public BigInteger this[int i, int j]
{
get { return M[i * B + j]; }
set { M[i * B + j] = value; }
}
}
//replace this class with your own implementation.
//derive from DependencyObject and use DependencyProperty to store data
public class BigInteger : DependencyObject
{
public BigInteger(int row, int col)
{
RowIndex = row;
ColumnIndex = col;
}
//Data Dependency Property
public string Data
{
get { return (string)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(string), typeof(BigInteger), new UIPropertyMetadata(""));
//RowIndex Dependency Property
public int RowIndex
{
get { return (int)GetValue(RowIndexProperty); }
set { SetValue(RowIndexProperty, value); }
}
public static readonly DependencyProperty RowIndexProperty =
DependencyProperty.Register("RowIndex", typeof(int), typeof(BigInteger), new UIPropertyMetadata(0));
//ColumnIndex Dependency Property
public int ColumnIndex
{
get { return (int)GetValue(ColumnIndexProperty); }
set { SetValue(ColumnIndexProperty, value); }
}
public static readonly DependencyProperty ColumnIndexProperty =
DependencyProperty.Register("ColumnIndex", typeof(int), typeof(BigInteger), new UIPropertyMetadata(0));
}
public class GridHelper
{
#region RowCount Property
/// <summary>
/// Adds the specified number of Rows to RowDefinitions.
/// Default Height is Auto
/// </summary>
public static readonly DependencyProperty RowCountProperty =
DependencyProperty.RegisterAttached(
"RowCount", typeof(int), typeof(GridHelper),
new PropertyMetadata(-1, RowCountChanged));
// Get
public static int GetRowCount(DependencyObject obj)
{
return (int)obj.GetValue(RowCountProperty);
}
// Set
public static void SetRowCount(DependencyObject obj, int value)
{
obj.SetValue(RowCountProperty, value);
}
// Change Event - Adds the Rows
public static void RowCountChanged(
DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
if (!(obj is Grid) || (int)e.NewValue < 0)
return;
Grid grid = (Grid)obj;
grid.RowDefinitions.Clear();
for (int i = 0; i < (int)e.NewValue; i++)
grid.RowDefinitions.Add(
new RowDefinition() { Height = GridLength.Auto });
//SetStarRows(grid);
}
#endregion
#region ColumnCount Property
/// <summary>
/// Adds the specified number of Columns to ColumnDefinitions.
/// Default Width is Auto
/// </summary>
public static readonly DependencyProperty ColumnCountProperty =
DependencyProperty.RegisterAttached(
"ColumnCount", typeof(int), typeof(GridHelper),
new PropertyMetadata(-1, ColumnCountChanged));
// Get
public static int GetColumnCount(DependencyObject obj)
{
return (int)obj.GetValue(ColumnCountProperty);
}
// Set
public static void SetColumnCount(DependencyObject obj, int value)
{
obj.SetValue(ColumnCountProperty, value);
}
// Change Event - Add the Columns
public static void ColumnCountChanged(
DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
if (!(obj is Grid) || (int)e.NewValue < 0)
return;
Grid grid = (Grid)obj;
grid.ColumnDefinitions.Clear();
for (int i = 0; i < (int)e.NewValue; i++)
grid.ColumnDefinitions.Add(
new ColumnDefinition() { Width = GridLength.Auto });
//SetStarColumns(grid);
}
#endregion
}
<Window x:Class="StackExchange.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid AutoGenerateColumns="True" Name="myGrid"/>
</Grid>
public DataTable Macierz;
public MainWindow()
{
InitializeComponent();
Macierz = new DataTable("Table");
Macierz.Columns.Add("Col1", typeof(int));
Macierz.Columns.Add("Col2", typeof(int));
Macierz.Columns.Add("Col3", typeof(int));
DataRow row1 = Macierz.NewRow();
row1["Col1"] = 1;
row1["Col2"] = 2;
row1["Col3"] = 3;
Macierz.Rows.Add(row1);
DataRow row2 = Macierz.NewRow();
row2["Col1"] = 4;
row2["Col2"] = 5;
row2["Col3"] = 6;
Macierz.Rows.Add(row2);
myGrid.DataContext = this;
myGrid.ItemsSource = Macierz.DefaultView;
}