简体   繁体   English

WPF 遍历数据网格

[英]WPF iterate through datagrid

Using WPF C#.NET4.5 using visual studio 2012 ulti.使用 WPF C#.NET4.5 使用 visual studio 2012 ulti。

Old winforms code:旧的 winforms 代码:

foreach (DataGridViewRow paretoRow in ParetoGrid.Rows)
{
       if ((Convert.ToInt32(paretoRow.Cells["CurrentPareto"].Value) < (Convert.ToInt32(paretoRow.Cells["NewPareto"].Value))))
       {
              paretoRow.Cells["pNew"].Value = downArrow
       }
}

As you can see each row I cycle through I check a specific cell, if true I then populate another cell.正如您所看到的,我循环遍历的每一行都会检查一个特定的单元格,如果为真,我就会填充另一个单元格。 This was good old winforms code I used many times before...however.这是我以前多次使用过的很好的旧 winforms 代码……但是。 Switching over to WPF was alot more different than i previously assumed.切换到 WPF 与我之前假设的大不相同。

DataGrid does not contain the Row property. DataGrid不包含Row属性。 Instead, I think you need to use:相反,我认为你需要使用:

DataGridRow paretoRow in paretogrid.Items

But im still at a loss on who to now get the cell.但我仍然不知道现在应该由谁来获得手机。

So my question is, is there syntax changes to perform, if so where?所以我的问题是,是否有语法更改要执行,如果是的话在哪里? Or as I'm beginning to believe datagrids in WPF operate with Objects more so than winforms thus not needing to use a propertie called "row", if this is the case what logic/syntax should i know use in this example?或者我开始相信 WPF 中的数据网格比 winforms 更能与对象一起操作,因此不需要使用称为“行”的属性,如果是这种情况,我应该知道在这个例子中使用什么逻辑/语法?

Thanks for your patience guys, think when I go home for the bank holiday I'll do a bit of WPF digging to see how different it actually is.感谢你们的耐心等待,想想当我 go 回家过银行假期时,我会做一些 WPF 挖掘,看看它实际上有多么不同。

I think first think you want to do is to get all rows of your DataGrid : 我想首先想你要做的是获取你的DataGrid所有行:

public IEnumerable<Microsoft.Windows.Controls.DataGridRow> GetDataGridRows(Microsoft.Windows.Controls.DataGrid grid)
{
    var itemsSource = grid.ItemsSource as IEnumerable;
    if (null == itemsSource) yield return null;
    foreach (var item in itemsSource)
    {
        var row = grid.ItemContainerGenerator.ContainerFromItem(item) as Microsoft.Windows.Controls.DataGridRow;
        if (null != row) yield return row;
    }
}

and then iterate through your grid: 然后遍历你的网格:

var rows = GetDataGridRows(nameofyordatagrid); 

foreach (DataGridRow row in rows)  
{  
  DataRowView rowView = (DataRowView)row.Item;
  foreach (DataGridColumn column in nameofyordatagrid.Columns)
  {
      if (column.GetCellContent(row) is TextBlock)
      {
          TextBlock cellContent = column.GetCellContent(row) as TextBlock;
          MessageBox.Show(cellContent.Text);
      }
  } 

People seem to be overcomplicating this, this worked for me: 人们似乎过于复杂,这对我有用:

foreach (System.Data.DataRowView dr in yourDataGrid.ItemsSource)
{
     MessageBox.Show(dr[0].ToString());
}

Yes, you are right. 是的,你是对的。 WPF DataGrid is built around better supporting the use of objects. WPF DataGrid是围绕更好地支持对象的使用而构建的。

You could use a ViewModel similar to the following. 您可以使用类似于以下的ViewModel。 Build them all into a collection and then set that collection as your ItemsSource . 将它们全部构建到一个集合中,然后将该集合设置为ItemsSource You would also need to use a ValueConverter if you want to display and image instead of a checkmark for pNew being true/false. 如果要显示和图像而不是pNew为true / false的复选标记,则还需要使用ValueConverter。

public class FooViewModel : INotifyPropertyChanged
{
    private int currentPareto;
    public int CurrentPareto 
    {
        get
        {
           return currentPareto;
        }
        set
        { 
            if (currentPareto == value)
                return;

            currentPareto = value;
            OnPropertyChanged("CurrentPareto");
            OnPropertyChanged("pNew");
        }
    }

    private int newPareto;
    public int NewPareto 
    {
        get
        {
           return newPareto;
        }
        set
        { 
            if (newPareto == value)
                return;

            newPareto = value;
            OnPropertyChanged("NewPareto");
            OnPropertyChanged("pNew");
        }
    }

    public bool pNew
    {
        get
        {
            return CurrentPareto < NewPareto;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Edit 编辑

To simplify it a little, you could use a base ViewModel class and use PropertyChanged weaving. 为了简化它,您可以使用基本ViewModel类并使用PropertyChanged编织。 The code would simplify to this: 代码将简化为:

public class FooViewModel : ViewModelBase
{
    public int CurrentPareto { get; set; }
    public int NewPareto { get; set; }
    public bool pNew { get { return CurrentPareto < NewPareto; } }
}

The 'simplest' answer, from Charles, did it for me.来自 Charles 的“最简单”答案为我做了。 But I used Items instead of ItemsSource .但我使用Items而不是ItemsSource

Now, for people getting this error:现在,对于出现此错误的人:

System.InvalidCastException
Unable to cast object of type 'MS.Internal.NamedObject' to type 'System.Data.DataRowView'.

What did it for me was disabling the DataGrid's property CanUserAddRows .它对我的作用是禁用 DataGrid 的属性CanUserAddRows This removes the placeholder line for a new line, thus removing the placeholder object (which is NOT a DataRowView, but something else).这将删除新行的占位符行,从而删除占位符 object(这不是 DataRowView,而是其他内容)。 If you already have this disabled, then I don't know.如果您已经禁用了此功能,那么我不知道。

Since I wanted to loop through each element of each row, I added another foreach :因为我想遍历每一行的每个元素,所以我添加了另一个foreach

foreach (System.Data.DataRowView dr in nameofyourgrid.Items)
{
    foreach (var item in dr.Row.ItemArray)
    {
        MessageBox.Show(item.ToString());
    }
}

In WPF you go about it a lot more dynamic and ObjectOrientated. 在WPF中,你会更加动态和ObjectOrientated。 You can bind the Column "pNew" on a Property of the element you put in the DataGrid , which returns downarrow. 您可以将列“pNew”绑定到放在DataGrid中的元素的Property上,该元素将返回downarrow。 If the value changes you can raise the Event PropertyChanged (Interface INotifyPropertyChanged ) and the bound Property will get reevaluated. 如果值更改,则可以引发Event PropertyChanged (接口INotifyPropertyChanged ),并且将重新评估绑定的Property。

Also interesting for beginning with WPF is DataTemplate , ControlTemplate , Converter . 从WPF开始也很有趣的是DataTemplateControlTemplateConverter Converter changes the Property Value to a usable Value for WPF (eg BoolToVisibility) when the Property gets called. 当调用Property时,Converter将属性值更改为WPF的可用值(例如BoolToVisibility)。 DataTemplate and ControlTemplate can be used to alter the appearance of the Control. DataTemplateControlTemplate可用于更改Control的外观。

There are several good Tutorials for WPF out there. WPF有几个很好的教程。 I would also recommend to look into the MVVM-Pattern to use as a between layer of your Businessobject and your WPF-Control, especially to handle things like what you try to do here. 我还建议调查MVVM-Pattern以用作Businessobject和WPF-Control的层之间,尤其是处理您尝试在此处执行的操作。

I don't even understand why is it just so complicated to get rows and their values in a datagrid. 我甚至不明白为什么在数据网格中获取行及其值这么复杂。 It feels like hell finding how. 感觉好像在寻找怎么样。 The api even give funny funny event names which is not so direct to the point also. api甚至给出了有趣的有趣事件名称,这也不是那么直接。 Why can't just people concentrate on the baseline and give what exactly is needed and not all sorts of different options with no use and sense at all. 为什么不能只是人们专注于基线并给出确切需要的东西而不是所有种类的不同选择,没有任何用处和意义。 I mean to eat all you need is a spoon and fork right. 我的意思是吃所有你需要的是一把勺子和叉子吧。 Never even changed since 100,000 years ago. 自从10万年前以来从未改变过。 This is my code thanks to the guy who mentioned some people just try to over-complicate things and waste your time. 这是我的代码,感谢那些提到有些人试图过度复杂化并浪费你的时间的人。

    private void dtaResultGrid_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        ActivateTestDatagridAccess();
    }

    public async void ActivateTestDatagridAccess()
    {
        try
        {
            await Task.Delay(500);
            foreach (System.Data.DataRowView dr in dtaResultGrid.ItemsSource)
            {
                for (int j = 0; j < dtaResultGrid.Columns.Count; j++)
                {
                    Console.WriteLine(dr[j].ToString());
                }
                Console.Write(Environment.NewLine);
            }
        }
        catch (Exception exrr)
        {
            Console.WriteLine(exrr.ToString());
        }
    }

if you fill your datagridview rows using an instance of a class (like struct_class) this would be the fastest way to have a foreach loop如果您使用 class 的实例(如 struct_class)填充 datagridview 行,这将是拥有 foreach 循环的最快方法

foreach (struct_class row in dgv.Items)
{
    MessageBox.Show(row.name);
}

为什么你不能只使用这个属性来获取行数,然后使用For循环来迭代?

dataGridView1.Rows.Count

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM