WPF遍历数据网格

iq3niunx  于 2023-08-07  发布在  其他
关注(0)|答案(9)|浏览(121)

使用WPF C#.NET4.5使用Visual Studio 2012 ulti.
旧的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
       }
}

字符串
正如您所看到的,我循环遍历的每一行都检查一个特定的单元格,如果为true,则填充另一个单元格。这是我以前用过很多次的很好的winforms代码。切换到WPF比我以前假设的要不同得多。
DataGrid不包含Row属性。相反,我认为你需要用途:

DataGridRow paretoRow in paretogrid.Items


但我仍然不知道现在谁能拿到手机。
所以我的问题是,是否有语法更改要执行,如果有,在哪里?或者,我开始相信WPF中的数据网格比winforms更能与对象一起操作,因此不需要使用一个名为“行”的属性,如果是这种情况,我应该知道在这个例子中使用什么逻辑/语法?
谢谢你们的耐心,当我回家过银行假期的时候,我会做一些WPF的挖掘,看看它到底有多大的不同。

8cdiaqws

8cdiaqws1#

人们似乎把这件事复杂化了,这对我很有效:

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

字符串

2uluyalo

2uluyalo2#

我认为首先要做的是获取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;
    }
}

字符串
然后遍历网格:

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);
      }
  }

gmxoilav

gmxoilav3#

是的,你是对的。WPF DataGrid是围绕更好地支持对象的使用而构建的。
您可以使用类似于以下内容的ViewModel。将它们全部构建到一个集合中,然后将该集合设置为您的ItemsSource。如果您想显示和图像,而不是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));
        }
    }
}

字符串

编辑

为了简化它,您可以使用基本ViewModel类并使用PropertyChanged织入。代码将简化为:

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

bakd9h0s

bakd9h0s4#

我甚至不明白为什么在数据网格中获取行和它们的值会如此复杂。我感觉像地狱找到如何。API甚至给予了有趣的有趣的事件名称,这也不是那么直接。为什么人们不能只关注基线,给予真正需要的东西,而不是各种各样的没有用处和意义的不同选择。我的意思是吃东西只需要一个勺子和叉子就可以了。从十万年前就没变过。这是我的代码,感谢那个提到有些人只是试图把事情复杂化,浪费你的时间的人。

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());
        }
    }

字符串

sz81bmfz

sz81bmfz5#

查尔斯的“最简单”的回答为我做了。但是我使用了Items而不是ItemsSource
现在,对于得到此错误的人:

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

字符串
对我来说,禁用DataGrid的属性CanUserAddRows是一件好事。这将删除新行的占位符行,从而删除占位符对象(它不是DataRowView,而是其他对象)。如果你已经禁用了这个,那我就不知道了。
因为我想循环遍历每行的每个元素,所以我添加了另一个foreach

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

ix0qys7i

ix0qys7i6#

在WPF中,您可以更加动态和面向对象地进行操作。您可以在DataGrid中放置的元素的属性上绑定“pNew”列,这将返回downarrow。如果该值发生更改,则可以引发事件PropertyChanged(接口INotifyPropertyChanged),并且将重新计算绑定属性。
对于以WPF开头的应用程序来说,同样有趣的是DataTemplateControlTemplateConverter。转换器将属性值更改为WPF可用的值(例如,BoolToVisibility)。DataTemplateControlTemplate可用于更改控件的外观。
有几个很好的教程为WPF在那里。我还建议您研究MVVM模式,将其用作Businessobject和WPF-Control的中间层,尤其是在处理类似于此处尝试执行的操作时。

h5qlskok

h5qlskok7#

如果使用类的示例(如struct_class)填充datagridview行,这将是拥有foreach循环的最快方式

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

字符串

vybvopom

vybvopom8#

如果您的DataGrid绑定到自定义对象集合(例如List<MyViewItem>),DataGridRow迭代显然不起作用。仅当使用DataTable/DataGridView作为DataGrid ItemsSource时。
可以迭代自定义DataGrid集合,但只有视图中的行具有已计算的绑定。
为了解决这个问题,我使用了BindingPropertyHelper解决方案作为Fallback:

public static class PropertyPathHelper
{
    public static object GetValue(object obj, string propertyPath)
    {
        Binding binding = new Binding(propertyPath);
        binding.Mode = BindingMode.OneTime;
        binding.Source = obj;
        BindingOperations.SetBinding(_dummy, Dummy.ValueProperty, binding);
        return _dummy.GetValue(Dummy.ValueProperty);
    }

    private static readonly Dummy _dummy = new Dummy();

    private class Dummy : DependencyObject
    {
        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(object), typeof(Dummy), new UIPropertyMetadata(null));
    }
}

字符串
以下代码将所有DataGrid行转换为新的(可迭代的)DataTable:

DataTable dt = new DataTable();
for (int i = 0; i < dataGrid.Columns.Count; i++)
{
    var c = dataGrid.Columns[i];

    if (c.Header != null)
        dt.Columns.Add(new DataColumn(c.Header.ToString()));
    else
        dt.Columns.Add();
}

for (int rowIndex = 0; rowIndex < dataGrid.Items.Count; rowIndex++)
{
    var item = dataGrid.Items[rowIndex];

    var newRow = dt.NewRow();

    bool written = false;
    for (int columnIndex = 0; columnIndex < dataGrid.Columns.Count; columnIndex++)
    {
        DataGridColumn column = dataGrid.Columns[columnIndex];

        FrameworkElement feColumn = column.GetCellContent(item);
        if (feColumn is TextBlock tb)
        {
            // binding loaded (in view)
            newRow[columnIndex] = tb.Text;
            written = true;
        }
        else if (column is DataGridTextColumn textColumn
            && textColumn.Binding is Binding bind)
        {
            // falback and evaluate binding explicit (out of view)
            object value = PropertyPathHelper.GetValue(item, bind.Path.Path);
            newRow[columnIndex] = value;
            written = true;
        }
    }

    if (written == false)
    {
        throw new InvalidOperationException($"Could not read row index {rowIndex} of DataGrid; Source item type: {item?.GetType()?.FullName}");
    }

    dt.Rows.Add(newRow);
}

polhcujo

polhcujo9#

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

dataGridView1.Rows.Count

字符串

相关问题