【问题标题】:One ObservableCollection per DataGridColumn in WPF DataGridWPF DataGrid 中每个 DataGridColumn 一个 ObservableCollection
【发布时间】:2014-08-29 21:33:37
【问题描述】:

使用MVVMLight 开发WPF 应用程序。

我正在尝试将DataGridAutoGenerateColumns 设置为False)中的每个DataGridColumn 绑定到每列一个ObservableCollection<string>I've already asked something similar 并收到了一个很好的答案,但这种方法的问题是项目会一次添加到 DataGrid 一行中。这种方法还引入了一个新的Model 类,这使得TwoWay 与实际Model 类的绑定成为问题,我需要与我的View 保持同步。

我的问题是:假设我有几个完全相同的计数/长度的ObservableCollection<string>,是否可以每列绑定一个ObservableCollection<string>?到目前为止,我的方法是这样的:

  • 在我的ViewModel 上创建一个ObservableCollection<ObservableCollection<string>>(我们将其命名为GridColumns)属性,其中包含我需要的每个ObservableCollections<string>
  • 将我的DataGridItemsSource绑定到GridColumns
  • 设置每个的绑定 DataGridColumnGridColumns 中的每个 ObservableCollection<string>

我似乎无法让它工作。我完全不接受这种方法吗?

编辑:

这是我想出的:

1) 创建了一个Model 类,它公开了ObservableCollection 属性

 public class AttributeListItems : ObservableObject
    {
        private ObservableCollection<string> category;
        public ObservableCollection<string> Category
        {
            get { return category; }
            set
            {
                if (category == value)
                {
                    return;
                }
                category = value;
                RaisePropertyChanged(() => Category);
            }
        }
        private ObservableCollection<string> fileValue;
        public ObservableCollection<string> FileValue
        {
            get { return fileValue; }
            set
            {
                if (fileValue == value)
                {
                    return;
            }
                fileValue = value;
                RaisePropertyChanged(() => FileValue);
            }
        }
    }

2) 在我的ViewModel 上创建了ObservableCollection&lt;AttributeListItems&gt; 的属性:

    private ObservableCollection<AttributeListItems> gridItems;
    public ObservableCollection<AttributeListItems> GridItems
    {
        get { return gridItems;  }
        set
        {
            if (gridItems == value)
            { return; }
            gridItems = value;
            RaisePropertyChanged(() => GridItems);
        }
    }

3) 在我的ViewModelSelectedAttribute 属性的setter 上(这是我想要重新填充GridItems 的时候)我添加了这个:

            gridItems.Clear();
            gridItems.Add(new AttributeListItems { 
                Category = selectedAttribute.Categories, 
                FileValue = selectedAttribute.FileValues } 
                );
            RaisePropertyChanged(() => GridItems);

4) 在我的View 上,我将DataGridItemsSource 设置为GridItems,并将其列绑定到Category,如下所示:

<DataGrid Grid.Row="0" Grid.ColumnSpan="2" Margin="5" AutoGenerateColumns="False" ItemsSource="{Binding GridItems}" EnableColumnVirtualization="True" CanUserReorderColumns="False" CanUserSortColumns="False" VerticalScrollBarVisibility="Visible" >
                <DataGrid.Columns>
                    <DataGridTextColumn Header="categories" Width="auto" Binding="{Binding Category}" />
                    <!--<DataGridTextColumn Header="file values" Width="auto" Binding="{Binding FileValue}" />-->
                </DataGrid.Columns>
</DataGrid>

当我运行它时,DataGrid 在列中只显示一行,它的文本是"(Collection)"。我尝试将列的绑定从 Category 更改为 Category/,这部分有效:它只显示 Category 集合的 first 值而不是全部,这是我现在卡住了。

【问题讨论】:

  • 您想在 DataGrid 中动态创建或删除列吗?
  • @bit nope 因为没有必要 - 列将包含有限数量的ObservableCollection&lt;T&gt;,其中所有的长度完全相同
  • 所以你的列需要是类别和文件值?
  • @bit 在最终结果中应该有一个附加列(最好是DataGridCheckBoxColumn)绑定到ObservableCollection&lt;bool&gt;,但由于我仍在尝试实现这一点,所以我没有包括它在示例/问题中

标签: .net wpf xaml mvvm wpfdatagrid


【解决方案1】:

首先,你需要一个

class RowItem
{
    bool IsChecked;
    string Category;
    string FileValue;
}

然后,您可以在任何需要的地方填充 RowItem 的集合,例如

GridData = new ObservableCollection<RowItem>();

最后在 XAML 中,

<DataGrid Grid.Row="0" Grid.ColumnSpan="2" Margin="5" AutoGenerateColumns="False" ItemsSource="{Binding GridData}" EnableColumnVirtualization="True" CanUserReorderColumns="False" CanUserSortColumns="False" VerticalScrollBarVisibility="Visible" >
                <DataGrid.Columns>
                    <DataGridCheckBoxColumn Header="Is Checked" Width="auto" IsChecked="{Binding IsChecked}" />
                    <DataGridTextColumn Header="Categories" Width="auto" Binding="{Binding Category}" />
                    <DataGridTextColumn Header="File values" Width="auto" Binding="{Binding FileValue}" />
                </DataGrid.Columns>
</DataGrid>

此外,您似乎有 selectedAttribute.CategoriesselectedAttribute.FileValues 集合作为数据源。 假设它们具有相同的长度,GridData 可以通过以下方式填充:

var rowItems = new List<RowItem>();

for( int i = 0; i < selectedAttribute.Categories.Count; i++ )
{
    var row = new RowItem 
    { 
        Category =  selectedAttribute.Categories[i],
        FileValues =  selectedAttribute.FileValues[i],
    };
    rowItems.Add(row);
}

GridData = new ObservableCollection<RowItem>(rowItems);

【讨论】:

  • 在你的代码中,它应该是selectedAttribute.Categories[i],而不是selectedAttribute[i].Categories[i]。我了解您的解决方案,但是如果您查看我在帖子中发布的链接,您会看到在之前的帖子中给了我类似的答案。我对这种方法的问题是TwoWay 绑定:当我在DataGrid 中更改Category 的值时(比如说第9 类),我还需要它来更新selectedAttribute.Categories[9]
  • 在我的评论中查看问题的 TwoWay 绑定部分。在这种情况下会发生什么?
  • 您将在 GridData 集合中获得更新后的值,因此在保存更改时,您必须设置一种机制来将网格数据转换回所需的对象
  • 是的,关于如何将更新后的值传回去有什么建议吗?
  • 难道不是简单地将转换为 GridData 循环..?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-07
  • 1970-01-01
  • 1970-01-01
  • 2015-01-26
  • 2013-10-14
相关资源
最近更新 更多