【问题标题】:C# WPF how to update observable collection after having programmatically updated datagrid - No MVVMC# WPF 如何在以编程方式更新数据网格后更新可观察集合 - 无 MVVM
【发布时间】:2019-06-02 22:37:44
【问题描述】:

我有一个与可观察集合链接的数据网格。 他们有大量我必须操作的列/属性。 我需要通过组合框对用户在运行时选择的列进行字符串替换。 所以我首先要做的是找出列的索引(在我们的例子中Description index=2从0开始),然后用下面的代码操作替换。变量iii表示当前行

DataGridRow row = (DataGridRow)dtgFeatures.ItemContainerGenerator.ContainerFromIndex(iii);
if (row != null)
{
    var content = dtgFeatures.Columns[indexColumnToOperateOn].GetCellContent(row);
    if (content != null)
    {
        string str = ((TextBlock)content).Text;
        if (str.ToUpper().Trim().Contains(tbxSrc.Text.ToUpper().Trim()))
        {
            ((TextBlock)content).Text = str.Replace(tbxSrc.Text, tbxDest.Text);
            obcCfgPartPrograms = (ObservableCollection < CfgPartPrograms >) dtgFeatures.ItemsSource;
        }
    }
}

在我们的示例中,我们可以将字符串“pccad”更改为“AAA”

这样“以图形方式”工作,但 observable 集合不会使用命令 obcCfgPartPrograms = (ObservableCollection ) dtgFeatures.ItemsSource; 进行回更新;

我知道我可以通过每个属性来做到这一点,但这对于

--编辑-- 对不起,我看到我没有说清楚。我的错。

所以我有很多属性(这里有 9 个,但可能更多),所以我不会写这样的东西:

if(comboBoxValue="Description")
    obc.Description = dtgFeatures[2,row];
else  if(comboBoxValue="Notes")
    obc.Description = dtgFeatures[4,row];

...

因为我可以手动编辑数据网格并将更改反映在可观察集合上

datagrid MANUAL EDIT ---> 可观察集合的变化

为什么不能以编程方式(例如使用字符串比较)编辑数据网格并在 obc 上反映更改?

datagrid 自动编辑 ---> 可观察集合的变化

简而言之: 1. 我能够更改数据网格 --> dtgFeatures[property_X,row_Y] = "AAAAAA"; 2.我希望能够自动改变obc[Y].X = "AAAAAA";

数量非常多。

感谢您的帮助 帕特里克

【问题讨论】:

  • 是否首先使用 MVVM?另外,为什么要更改 UI 元素而不是更改 ObservableCollection 并触发 OnPropertyChanged 事件?
  • 没有 MVVM 很抱歉。至于其余的请看我的编辑
  • 如果您可以以编程方式编辑 DataGrid,为什么不能以编程方式对 ObservableCollection 执行相同操作?
  • 因为可以使用索引和坐标访问数据网格 --> datagrid.Cell[x,y]。我不知道用 observable 集合做同样的方法 --> obc[member x, line j]
  • Finding an Index in an ObservableCollection,虽然它们是数字索引

标签: c# wpf properties datagrid observablecollection


【解决方案1】:

如果TextBlock 绑定到CfgPartPrograms 对象的源属性,您可以使用GetBindingExpression 方法获取该属性的名称。然后,您可以使用反射将属性设置为新值:

DataGridRow row = (DataGridRow)dtgFeatures.ItemContainerGenerator.ContainerFromIndex(iii);
if (row != null)
{
    var content = dtgFeatures.Columns[indexColumnToOperateOn].GetCellContent(row);
    if (content != null)
    {
        TextBlock textBlock = (TextBlock)content;
        if (textBlock.Text.ToUpper().Trim().Contains(tbxSrc.Text.ToUpper().Trim()))
        {
            string str = textBlock.Text.Replace(tbxSrc.Text, tbxDest.Text);
            textBlock.Text = str;
            BindingExpression be = textBlock.GetBindingExpression(TextBlock.TextProperty);
            if (be != null && be.ParentBinding != null && be.ParentBinding.Path != null && !string.IsNullOrEmpty(be.ParentBinding.Path.Path))
            {
                object cfgPartPrograms = textBlock.DataContext;
                if (cfgPartPrograms != null)
                {
                    System.Reflection.PropertyInfo pi = typeof(CfgPartPrograms).GetProperty(be.ParentBinding.Path.Path);
                    if (pi != null)
                        pi.SetValue(cfgPartPrograms, str);
                }
            }
        }
    }
}

【讨论】:

  • 这听起来很有希望!除了它不起作用。我进行了一些编辑,不仅将其引用到第 0 行和第 0 列(需要同行评审的编辑)。但除此之外,即使更新了数据网格,be bindingExpression 也始终为 null,因此永远不会输入 inter if(be!null) ;-(
【解决方案2】:

是的,可以这样做。要经过的路径如下:

想象一下有以下类:

public class MyClass
{
    public string s1 { get; set; }
    public string s2 { get; set; }
    public string s3 { get; set; }

    public MyClass(string _s1, string _s2, string _s3)
    {
        s1 = _s1;
        s2 = _s2;
        s3 = _s3;
    }
}

所以现在我们可以创建并填充 obc:

var obc = new ObservableCollection<MyClass>();
obc.Add(new MyClass("a1","a2","a3"));
obc.Add(new MyClass("b1", "b2","b3"));

我们可以修改它:

foreach (var itemObc in obc)
{
    PropertyInfo[] Fields = itemObc.GetType().GetProperties();
        foreach (PropertyInfo field in Fields)
    {
    var currentField = field.GetValue(itemObc, null);
    var t = currentField.GetType();
    if (t == typeof(string))
        field.SetValue(itemObc, "XXXX");
    }
}

结果是:

你甚至可以使用扩展:

public static class ObservableCollectionExtensions
{
public static ObservableCollection<T> SetValue<T>(this ObservableCollection<T> obc, int rowNumFromZero, int propNumFromZero, string str)
{
    int rowCounter = -1;
    foreach (var itemObc in obc)
    {
        rowCounter++;
        PropertyInfo[] Fields = itemObc.GetType().GetProperties();
        int propCounter = -1;
        foreach (PropertyInfo field in Fields)
        {
            propCounter++;
            if (rowCounter == rowNumFromZero)
            {
                var currentField = field.GetValue(itemObc, null);
                if (currentField != null)
                {
                    var t = currentField.GetType();
                    if (t == typeof(string) && propCounter == propNumFromZero)
                        field.SetValue(itemObc, str);
                }
            }
        }
    }
    return obc;
}

}

并像这样使用它:

obc.SetValue(numRow, numCol, strNewValue);

【讨论】:

    【解决方案3】:

    您应该改为修改ObservableCollection 中的数据。通常,始终避免操作 UI 控件。修改您的数据,并在必要时引发 OnPropertyChanged 事件。

    【讨论】:

    • 不,我看不到我的编辑。
    猜你喜欢
    • 2012-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-04
    • 1970-01-01
    • 1970-01-01
    • 2019-04-09
    相关资源
    最近更新 更多