0

所有,我正在创建一个DataGrid在运行时“绑定”到 a 的数据集。我提取了一些数据,这些数据用于构建一个继承自ObservableCollection<T>. 有问题的班级是

public class ResourceData : ObservableCollection<ResourceRow>
{
   public ResourceData(List<ResourceRow> resourceRowList) : base()
   {
      foreach (ResourceRow row in resourceRowList)
         Add(row);
   }
}

public class ResourceRow
{
   private string keyIndex;
   private string fileName;
   private string resourceName;
   private List<string> resourceStringList;

   public string KeyIndex
   {
      get { return keyIndex; }
      set { keyIndex = value; }
   }

   public string FileName
   {
      get { return fileName; }
      set { fileName = value; }
   }

   public string ResourceName
   {
      get { return resourceName; }
      set { resourceName = value; }
   }

   public List<string> ResourceStringList
   {
      get { return resourceStringList; }
      set { resourceStringList = value; }
   }
}

我从一个名为 的方法返回一个ResourceData对象BuildDataGrid(),定义为

private ResourceData BuildDataGrid(Dictionary<string, string> cultureDict)
{
    // ...
}

然后我通过DataGrid_ItemSourceResourceData

dataGrid.ItemSource = BuiltDataGrid(cultureDictionary);

但是,这并没有正确扩展ResourceStringListinside ResourceRow。我得到显示:

数据网格

我的问题是:如何修改我的ResourceRow类以允许DataGrid自动读取和显示ResourceData对象的内容?我想ResourceStringList在单独的列中显示每个项目。

谢谢你的时间。

4

3 回答 3

1

这是我的解决方案-我更改了控件,而不是 ResourceRow,但我认为它可以实现您想要的。

我们只需在 xaml 中创建一个带有设计时列的 DataGrid,然后在控件的构造函数中动态添加运行时列。有几件事要记住——我们假设 ResourceData 的第一行是所有行的好模型,因为这是我们用来确定要添加到构造函数中的数据网格的列的模型。其次,由于 ResourceRow 没有实现 INotifyPropertyChanged,我们不会获得来自 ResourceStringList 的列的更新值——但这很容易改变。

代码隐藏:

namespace WpfApplication
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            ResourceData data = GetData();
            _dataGrid.ItemsSource = data;

            for (int i = 0; i < data[0].ResourceStringList.Count; i++)
            {
                DataGridTextColumn column = new DataGridTextColumn();
                column.Binding = new Binding(string.Format("ResourceStringList[{0}]", i));
                column.Header = string.Format("dynamic column {0}", i);
                _dataGrid.Columns.Add(column);
            }
        }

        public ResourceData GetData()
        {
            List<ResourceRow> rows = new List<ResourceRow>();

            for (int i = 0; i < 5; i++)
            {
                rows.Add(new ResourceRow() { KeyIndex = i.ToString(), FileName = string.Format("File {0}", i), ResourceName = string.Format("Name {0}", i), ResourceStringList = new List<string>() { "first", "second", "third" } });
            }
            return new ResourceData(rows);
        }
    }

    public class ResourceData : ObservableCollection<ResourceRow>
    {
        public ResourceData(List<ResourceRow> resourceRowList)
            : base()
        {
            foreach (ResourceRow row in resourceRowList)
                Add(row);
        }
    }

    public class ResourceRow
    {
        private string keyIndex;
        private string fileName;
        private string resourceName;
        private List<string> resourceStringList;

        public string KeyIndex
        {
            get { return keyIndex; }
            set { keyIndex = value; }
        }

        public string FileName
        {
            get { return fileName; }
            set { fileName = value; }
        }

        public string ResourceName
        {
            get { return resourceName; }
            set { resourceName = value; }
        }

        public List<string> ResourceStringList
        {
            get { return resourceStringList; }
            set { resourceStringList = value; }
        }
    }
}

xml:

<Window x:Class="WpfApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid x:Name="_dataGrid" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding KeyIndex}" Header="Key Index"/>
                <DataGridTextColumn Binding="{Binding FileName}" Header="File Name"/>
                <DataGridTextColumn Binding="{Binding ResourceName}" Header="Resource Name"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>
于 2013-04-18T22:36:17.677 回答
0

您的属性需要从 INotifyPropertyChanged 继承,以便它们可以更新 UI,您的 ViewModel 也是如此。让您的视图模型(或背后的代码)从 INotifyPropertyChanged 继承。实现接口,然后您可以为您的属性执行此操作。

    private string _keyIndex= string.Empty;
    public string KeyIndex
    {
        get { return this._keyIndex; }

       set
       {
            this._keyIndex= value;
            this.RaisePropertyChangedEvent("KeyIndex");
        }
   }
于 2013-04-18T21:35:49.617 回答
0

@Andrew 的回答是正确的,但我喜欢简单易用,所以我实现了一种方法,可以自动设置列并将其绑定到具有我想要的名称的数据网格,而不必使用数据网格列。

声明一个从属性继承的列名类,如下所示:

public class ColumnNameAttribute : Attribute
{
    public ColumnNameAttribute(string Name) { this.Name = Name; }
    public string Name { get; set; }

}

使用列名称装饰您的模型,如下所示:

public class Data
  {
        [ColumnName("Name")]
        public string Name{ get; set; }
        [ColumnName("Customer")]
        public string Client { get; set; }
        [ColumnName("Activity Type")]
        public string Activity_Type { get; set; }
    }

将 AutoGenerateColumns 设置为 True,然后添加此事件处理程序:

 private void gen_AutoGridColumns(object sender, DataGridAutoGeneratingColumnEventArgs e)
    {           
        var desc = e.PropertyDescriptor as PropertyDescriptor;
        if (desc.Attributes[typeof(ColumnNameAttribute)] is ColumnNameAttribute att) e.Column.Header = att.Name;

        //set the width for each column           
        e.Column.Width = new DataGridLength(1, DataGridLengthUnitType.Star);            
    }

您现在可以跳过将 DataGridColumns 定义添加到 DataGrid 中,并且仍然可以将它们命名为您想要的任何名称。

于 2018-12-07T15:02:21.657 回答