2013-08-26 43 views
11

我有一個數據網格這需要得到填補動態地。填充一個DataGrid動態列

的tablelayout是這樣的:

id | image | name | Description | Name-1 | Name-N 

第一4列是靜態的其他是動態的。用戶應該能夠根據需要添加儘可能多的用戶。

我嘗試把它們彼此相鄰表中的多個用戶的數據進行比較。

現在我有一個列表框whitch containes動態生成列的名稱和FILLES靜態列的方法。我也可以爲每個用戶加載數據。現在我需要將它們合併到一個大表中。

的主要問題是現在:如何把「使用用戶數據」,並在一個DataGrid中的靜態內容。

+0

是顯示這些信息的唯一方法嗎? –

+0

我不確定你要求什麼。 – Wr4thon

+0

Johannes看到我的答案,這樣你就能明白我爲什麼這麼問了。 –

回答

20

至少有三種方式這樣做的:

  1. 從代碼隱藏
  2. 使用一個DataTable作爲的ItemsSource *
  3. 使用CustomTypeDescriptor手動修改DataGrid的列

    *推薦使用簡單


第一種方法:使用code-behind在運行時生成DataGrid的列。這實現起來很簡單,但也許感覺有點hackish,特別是如果你使用MVVM。所以,你有你的DataGrid固定欄目:

// add new columns to the data grid 
void AddColumns(string[] newColumnNames) 
{ 
    foreach (string name in newColumnNames) 
    { 
     grid.Columns.Add(new DataGridTextColumn { 
      // bind to a dictionary property 
      Binding = new Binding("Custom[" + name + "]"), 
      Header = name 
     }); 
    } 
} 

你會想:

<DataGrid x:Name="grid"> 
    <DataGrid.Columns> 
     <DataGridTextColumn Binding="{Binding id}" Header="id" /> 
     <DataGridTextColumn Binding="{Binding image}" Header="image" /> 
    </DataGrid.Columns> 
</DataGrid> 

當你有你的「名稱」準備好了,然後通過添加/刪除列,如修改網格創建一個應該包含原始類的包裝類,以及一個包含自定義屬性的字典。比方說,你的主要行類是「用戶」,那麼你會希望有一個包裝類是這樣的:

public class CustomUser : User 
{ 
    public Dictionary<string, object> Custom { get; set; } 

    public CustomUser() : base() 
    { 
     Custom = new Dictionary<string, object>(); 
    } 
} 

填充ItemsSource這一新的「CustomUser」類的集合:

void PopulateRows(User[] users, Dictionary<string, object>[] customProps) 
{ 
    var customUsers = users.Select((user, index) => new CustomUser { 
     Custom = customProps[index]; 
    }); 
    grid.ItemsSource = customUsers; 
} 

所以它綁在一起,例如:

var newColumnNames = new string[] { "Name1", "Name2" }; 
var users = new User[] { new User { id="First User" } }; 
var newProps = new Dictionary<string, object>[] { 
    new Dictionary<string, object> { 
     "Name1", "First Name of First User", 
     "Name2", "Second Name of First User", 
    }, 
}; 
AddColumns(newColumnNames); 
PopulateRows(users, newProps); 

第二方法:使用DataTable。這使得在引擎蓋下使用自定義類型的基礎結構,但更易於使用。只要綁定DataGrid的ItemsSourceDataTable.DefaultView屬性:

<DataGrid ItemsSource="{Binding Data.DefaultView}" AutoGenerateColumns="True" /> 

然後,你可以定義列,只要你喜歡,如:

Data = new DataTable(); 

// create "fixed" columns 
Data.Columns.Add("id"); 
Data.Columns.Add("image"); 

// create custom columns 
Data.Columns.Add("Name1"); 
Data.Columns.Add("Name2"); 

// add one row as an object array 
Data.Rows.Add(new object[] { 123, "image.png", "Foo", "Bar" }); 

3方法:化妝使用的可擴展性.Net的類型系統。具體來說,使用CustomTypeDescriptor。這允許您在運行時創建自定義類型;這反過來使您能夠告訴DataGrid,您的類型具有屬性「Name1」,「Name2」,...「NameN」或其他任何你想要的。有關此方法的一個簡單示例,請參閱here

+2

我發現DataTable方法是最簡單和最有效的解決方案。 –

+0

有沒有人使用方法3在DataGrid中成功自動生成列?我已經定義了自定義類型描述符,我可以綁定到它的屬性,但是自動生成的列不起作用。 – Jesse

+0

如果我們想在同一個數據網格中編輯和更新數值,該怎麼辦? – Shelly

0

如果您不需要顯示成一個大的數據網格(表),那麼你可以有一個的DataGrid編號,圖片,名稱,描述當一條記錄上DataGrid中被選中,那麼您使用與所選記錄相關的圖像名稱來顯示/刷新列表框

+0

嗯,我不認爲這會解決我的問題。我有一個包含一些數據的大表(不管是誰),現在我需要將多個名稱與記錄進行比較。因此,對於每個記錄,我需要「N」個Colummns來直接比較兩個或更多個人。即G。 :記錄1:1; tmp.png; Foo; bar;成功;未成功記錄2:2; tmp2.png; Foo1; bar2;未成功;成功 – Wr4thon

4

第二種方法:使用DataTable。這使得在引擎蓋下使用自定義類型的基礎結構,但更易於使用。只需將DataGrid的ItemsSource綁定到DataTable.DefaultView屬性:

這幾乎可以工作,但不是綁定到DataTable.DefaultView屬性屬性,而是創建了DataView類型的屬性並綁定到該屬性。

<DataGrid ItemsSource="{Binding DataView, Mode=TwoWay}" AutoGenerateColumns="True" />

這樣的結合是兩個辦法,結合DataTable.DefaultView不能是雙向綁定。在視圖模型

public DataView DataView 
    { 
     get { return _dataView; } 
     set 
     { 
      _dataView = value; 
      OnPropertyChanged("DataView"); 
     } 
    } 

在此設置下我不僅可以動態定義的列時,視圖模型被初始化,但可以更新和動態改變數據表在任何時間。在使用上述McGarnagle定義的方法時,當用新數據源更新DataTable時,視圖模式不會刷新。