Berikut adalah solusi untuk Binding Columns di datagrid. Karena properti Columns adalah ReadOnly, seperti yang diketahui semua orang, saya membuat Attached Property yang disebut BindableColumns yang memperbarui Kolom di DataGrid setiap kali koleksi berubah melalui acara CollectionChanged.
Jika kita memiliki Collection of DataGridColumn's
public ObservableCollection<DataGridColumn> ColumnCollection
{
get;
private set;
}
Kemudian kita bisa mengikat BindableColumns ke ColumnCollection seperti ini
<DataGrid Name="dataGrid"
local:DataGridColumnsBehavior.BindableColumns="{Binding ColumnCollection}"
AutoGenerateColumns="False"
...>
The Attached Property BindableColumns
public class DataGridColumnsBehavior
{
public static readonly DependencyProperty BindableColumnsProperty =
DependencyProperty.RegisterAttached("BindableColumns",
typeof(ObservableCollection<DataGridColumn>),
typeof(DataGridColumnsBehavior),
new UIPropertyMetadata(null, BindableColumnsPropertyChanged));
private static void BindableColumnsPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
DataGrid dataGrid = source as DataGrid;
ObservableCollection<DataGridColumn> columns = e.NewValue as ObservableCollection<DataGridColumn>;
dataGrid.Columns.Clear();
if (columns == null)
{
return;
}
foreach (DataGridColumn column in columns)
{
dataGrid.Columns.Add(column);
}
columns.CollectionChanged += (sender, e2) =>
{
NotifyCollectionChangedEventArgs ne = e2 as NotifyCollectionChangedEventArgs;
if (ne.Action == NotifyCollectionChangedAction.Reset)
{
dataGrid.Columns.Clear();
foreach (DataGridColumn column in ne.NewItems)
{
dataGrid.Columns.Add(column);
}
}
else if (ne.Action == NotifyCollectionChangedAction.Add)
{
foreach (DataGridColumn column in ne.NewItems)
{
dataGrid.Columns.Add(column);
}
}
else if (ne.Action == NotifyCollectionChangedAction.Move)
{
dataGrid.Columns.Move(ne.OldStartingIndex, ne.NewStartingIndex);
}
else if (ne.Action == NotifyCollectionChangedAction.Remove)
{
foreach (DataGridColumn column in ne.OldItems)
{
dataGrid.Columns.Remove(column);
}
}
else if (ne.Action == NotifyCollectionChangedAction.Replace)
{
dataGrid.Columns[ne.NewStartingIndex] = ne.NewItems[0] as DataGridColumn;
}
};
}
public static void SetBindableColumns(DependencyObject element, ObservableCollection<DataGridColumn> value)
{
element.SetValue(BindableColumnsProperty, value);
}
public static ObservableCollection<DataGridColumn> GetBindableColumns(DependencyObject element)
{
return (ObservableCollection<DataGridColumn>)element.GetValue(BindableColumnsProperty);
}
}
CollectionChanged
peristiwa koleksi kolom, namun Anda tidak pernah membatalkan pendaftarannya. Dengan cara itu,DataGrid
akan tetap hidup selama model tampilan ada, meskipun template kontrol yang berisiDataGrid
di tempat pertama telah diganti sementara itu. Apakah ada cara yang dijamin untuk membatalkan registrasi event handler lagi saatDataGrid
tidak diperlukan lagi?dataGrid.Columns.Add(column)
DataGridColumn dengan Header 'X' sudah ada di koleksi Kolom dari datagrid. DataGrids tidak dapat berbagi kolom dan tidak dapat berisi contoh kolom duplikat.Saya telah melanjutkan penelitian saya dan belum menemukan cara yang masuk akal untuk melakukan ini. Properti Kolom di Datagrid bukanlah sesuatu yang bisa saya ikat, sebenarnya itu hanya baca.
Bryan menyarankan sesuatu untuk dilakukan dengan AutoGenerateColumns jadi saya melihatnya. Ini menggunakan refleksi .Net sederhana untuk melihat properti objek di ItemsSource dan menghasilkan kolom untuk masing-masing objek. Mungkin saya bisa menghasilkan tipe dengan cepat dengan properti untuk setiap kolom tetapi ini semakin keluar jalur.
Karena masalah ini sangat mudah ditemukan dalam kode, saya akan tetap menggunakan metode ekstensi sederhana yang saya panggil setiap kali konteks data diperbarui dengan kolom baru:
sumber
Saya telah menemukan artikel blog oleh Deborah Kurata dengan trik yang bagus bagaimana menunjukkan jumlah variabel kolom dalam datagrid:
Mengisi DataGrid dengan Kolom Dinamis di Aplikasi Silverlight menggunakan MVVM
Pada dasarnya, dia membuat
DataGridTemplateColumn
dan menempatkanItemsControl
di dalam yang menampilkan banyak kolom.sumber
Saya berhasil memungkinkan untuk menambahkan kolom secara dinamis hanya dengan menggunakan sebaris kode seperti ini:
Mengenai pertanyaan, ini bukan solusi berbasis XAML (karena seperti yang disebutkan tidak ada cara yang masuk akal untuk melakukannya), juga bukan solusi yang akan beroperasi langsung dengan DataGrid.Columns. Ini benar-benar beroperasi dengan ItemsSource terikat DataGrid, yang mengimplementasikan ITypedList dan dengan demikian menyediakan metode kustom untuk pengambilan PropertyDescriptor. Di satu tempat dalam kode, Anda dapat menentukan "baris data" dan "kolom data" untuk kisi Anda.
Jika Anda ingin:
Anda bisa menggunakan misalnya:
dan grid Anda menggunakan pengikatan ke MyItemsCollection akan diisi dengan kolom yang sesuai. Kolom tersebut dapat dimodifikasi (baru ditambahkan atau yang sudah ada dihapus) pada waktu proses secara dinamis dan grid akan secara otomatis menyegarkan koleksi kolomnya.
DynamicPropertyDescriptor yang disebutkan di atas hanyalah peningkatan ke PropertyDescriptor biasa dan memberikan definisi kolom yang sangat diketik dengan beberapa opsi tambahan. DynamicDataGridSource sebaliknya akan bekerja dengan baik pada acara dengan PropertyDescriptor dasar.
sumber
Membuat versi jawaban yang diterima yang menangani berhenti berlangganan.
sumber
Anda dapat membuat kontrol pengguna dengan definisi kisi dan menentukan kontrol 'anak' dengan berbagai definisi kolom di xaml. Induk membutuhkan properti ketergantungan untuk kolom dan metode untuk memuat kolom:
Induk:
Anak Xaml:
Dan akhirnya, bagian yang sulit adalah menemukan tempat untuk memanggil 'LoadGrid'.
Saya berjuang dengan ini tetapi membuat semuanya berfungsi dengan menelepon setelah
InitalizeComponent
di konstruktor jendela saya (childGrid adalah x: nama di window.xaml):Entri blog terkait
sumber
Anda mungkin dapat melakukan ini dengan AutoGenerateColumns dan DataTemplate. Saya tidak yakin apakah itu akan berhasil tanpa banyak pekerjaan, Anda harus bermain-main dengannya. Jujur saja jika Anda sudah memiliki solusi yang berfungsi, saya tidak akan membuat perubahan dulu kecuali ada alasan besar. Kontrol DataGrid menjadi sangat baik tetapi masih membutuhkan beberapa pekerjaan (dan saya memiliki banyak pembelajaran yang harus dilakukan) untuk dapat melakukan tugas-tugas dinamis seperti ini dengan mudah.
sumber
Ada contoh cara yang saya lakukan secara terprogram:
sumber