English 中文(简体)
我怎样才能将 Wpf DataGridColumn 绑在物体上?
原标题:How can I bind Wpf DataGridColumn to an object?
  • 时间:2009-05-19 17:16:48
  •  标签:
  • wpf
  • datagrid
I want to bind the columns of my WPF DataGrid to some objects in a Dictionary like this: Binding Path=Objects[i] where Objects is my Dictionary of objects, so that each cell will represent an Object element. How can I do that? I suppose that I need to create a template for my cell, which I did, but how to get the result of column binding in my template? I know that by default the content of a DataGridCell is a TextBlock and it s Text property is set through column binding result, but if that result is an object I guess that I have to create a ContentTemplate. How do I do that, as the stuff I tried is not displaying anything. Here it is what I tried: So, to make myself completly clear, i want to get in CurrentObject property of my DataGridCellControl the current object that should result if I set the column binding in my data grid like this Path=Objects[i]. Thank you for any suggestion, John.
问题回答
Try this: Where in ItemsSource="{Binding ElementName=window1, Path=Users, Mode=TwoWay}" ElementName is the name of the Window in XAML (just add x:Name="window1" to the Window tag as with any other ontrol. Users is a List, should work the same with Dictionary Mode=TwoWay means that if the grid gets modified, the list will get modified too, and vice versa (Two way binding) EDIT: Try this: XAML: C#: public class TheClass { public int Col1, Col2, Col3; public Dictionary otherColumns = new Dictionary(); } public class OtherColumns { public string ColumnName; public int Value; } And call this method under Window_Loaded: private void PopulateListView() { TheClass c = new TheClass(); c.Col1 = 10; c.Col2 = 20; c.Col3 = 30; c.otherColumns.Add(0, new OtherColumns() { ColumnName = "Col4", Value = 40 }); c.otherColumns.Add(1, new OtherColumns() { ColumnName = "Col5", Value = 50 }); c.otherColumns.Add(3, new OtherColumns() { ColumnName = "Col6", Value = 60 }); DataTable table = new DataTable(); // adding regular columns table.Columns.Add("Col1", typeof(int)); table.Columns.Add("Col2", typeof(int)); table.Columns.Add("Col3", typeof(int)); // adding dynamic columns foreach (KeyValuePair pair in c.otherColumns) { table.Columns.Add(pair.Value.ColumnName, typeof(int)); } DataRow row = table.NewRow(); // adding regular column values to the DataTable row["Col1"] = c.Col1; row["Col2"] = c.Col2; row["Col3"] = c.Col3; // adding dynamic column values to the DataTable foreach (KeyValuePair pair in c.otherColumns) { row[pair.Value.ColumnName] = pair.Value.Value; } table.Rows.Add(row); // Start binding the table. gridViewTest.Columns.Clear(); System.Windows.Controls.GridViewColumn gvc; Binding binding; foreach (DataColumn column in table.Columns) { gvc = new System.Windows.Controls.GridViewColumn(); binding = new System.Windows.Data.Binding(); binding.Path = new PropertyPath(column.ColumnName); binding.Mode = BindingMode.OneWay; gvc.Header = column.Caption; gvc.DisplayMemberBinding = binding; gridViewTest.Columns.Add(gvc); } listViewTest.DataContext = table; } I m not saying it s the best solution, but it could help. Let me know.
I made some helper classes so I could use the DataGrid as a kind of DataTable. In other words, I wanted the formatting, sorting, and polished look of the DataGrid without having to pre-fab some classes beforehand. The main reason I wanted this was for a testing suite, I wanted to be able to create an arbitrary number of columns and at runtime. Here s what I got public class DataRow { internal List Items = new List(); public object this[string value] { get { return Items[Convert.ToInt32(value)]; } } public string GetString(int index) { return Items[index].ToString(); } public object GetObject(int index) { return Items[index]; } public DataRow(params object[] values) { if (values == null || values.Length < 1) throw new Exception("You must pass in some values"); Items.AddRange(values); } } public class GridConstructor { public List Rows = new List(); private DataRow headers; public GridConstructor(DataRow head) { headers = head; } public void BuildInto(DataGrid grid) { grid.AutoGenerateColumns = false; grid.Columns.Clear(); int totalCols = 0; Type headType = headers.GetType(); for (int i = 0; i < headers.Items.Count; i++) { grid.Columns.Add(GetCol(headers.GetString(i), String.Concat("[", i.ToString(),"]"))); totalCols++; } int finalWidth = totalCols * (int)grid.ColumnWidth.Value + 15; grid.Width = finalWidth; grid.ItemsSource = Rows; } private DataGridTextColumn GetCol(string header, string binding) { DataGridTextColumn col = new DataGridTextColumn(); col.IsReadOnly = true; col.Header = header; col.Binding = new Binding(binding); return col; } public DataGrid Create(int colSize) { DataGrid grid = new DataGrid(); grid.ColumnWidth = colSize; grid.CanUserAddRows = false; grid.AlternationCount = 2; BuildInto(grid); return grid; } } Putting this together, this is a sample use: void SimpleTest_Loaded(object sender, RoutedEventArgs e) { DataRow headers = new DataRow("Level", "Weapon Type", "vs None", "vs Leather", "vs Studded", "vs Brigandine"); GridConstructor gridConstructor = new GridConstructor(headers); var weaponType = "Slash"; for (int level = 1; level < 10; level++) { int damage = DiceCup.RollMulti(8, level); int damCloth = damage - DiceCup.RollMulti(2, level); int damLeather = damage - DiceCup.RollMulti(3, level); int damStudded = damage - DiceCup.RollMulti(4, level); int damBrigandine = damage - DiceCup.RollMulti(5, level); DataRow row = new DataRow(level, weaponType, damage, damCloth, damLeather, damStudded, damBrigandine); gridConstructor.Rows.Add(row); } //Create the grid. var grid = gridConstructor.Create(100); //Create a chart. Chart chart = new Chart(); chart.Height = 200; chart.LegendTitle = "Legend"; chart.Title = "Slash vs Armor Types"; chart.DataContext = gridConstructor.Rows; //Create our series, or lines. LineSeries slashVsNone = new LineSeries(); slashVsNone.Title = "vs None"; slashVsNone.DependentValueBinding = new Binding("[2]"); slashVsNone.IndependentValueBinding = new Binding("[0]"); slashVsNone.ItemsSource = gridConstructor.Rows; chart.Series.Add(slashVsNone); //Presentation is a stackpanel on the page. presentation.Children.Add(grid); presentation.Children.Add(chart); } And the output: alt text http://quiteabnormal.com/images/codeSample.jpg Please note that the grid coloring is from universal styles set on the page. If you use the GridConstructor.BuildInto() method you can specify a grid you ve pre-formatted yourself in Blend or somesuch. Just one thing, the GridConstructor makes some assumptions about the column s initial settings. You can change the class to make it more customizable if you like, but this is what I needed so I wanted to be able to make it without fuss.




相关问题
WPF convert 2d mouse click into 3d space

I have several geometry meshes in my Viewport3D, these have bounds of (w:1800, h:500, d:25). When a user clicks in the middle of the mesh, I want the Point3D of (900, 500, 25)... How can I achieve ...

Editing a xaml icons or images

Is it possible to edit a xaml icons or images in the expression design or using other tools? Is it possible to import a xaml images (that e.g you have exported) in the expression designer for editing?...

WPF: writing smoke tests using ViewModels

I am considering to write smoke tests for our WPF application. The question that I am faced is: should we use UI automation( or some other technology that creates a UI script), or is it good enough to ...

WPF - MVVM - NHibernate Validation

Im facing a bit of an issue when trying to validate a decimal property on domain object which is bound to a textbox on the view through the viewmodel. I am using NHibernate to decorate my property on ...

How do WPF Markup Extensions raise compile errors?

Certain markup extensions raise compile errors. For example StaticExtension (x:Static) raises a compile error if the referenced class cannot be found. Anyone know the mechanism for this? Is it baked ...

WPF design-time context menu

I am trying to create a custom wpf control, I m wondering how I can add some design-time features. I ve googled and can t seem to get to my goal. So here s my simple question, how can I add an entry ...

How to combine DataTrigger and EventTrigger?

NOTE I have asked the related question (with an accepted answer): How to combine DataTrigger and Trigger? I think I need to combine an EventTrigger and a DataTrigger to achieve what I m after: when ...