2010-04-20 11 views
8

Her şeyi denedim ve hiçbir yere gitmedim, bu yüzden birisinin bana bir an verebileceğini umuyorum. Veri ızgarasındaki verileri başarılı bir şekilde çekmek için bağlayıcıyı alamıyorum.WPF DataGrid'in TemplateColumns kullanarak DataTrid'e bağlanması

I MyDataType arasında birden çok sütun içeren bir DataTable var

public class MyData 
{ 
    string nameData {get;set;} 
    bool showData {get;set;} 
} 

MyDataType DataTable bir test

DataTable GetDummyData() 
{ 
    DataTable dt = new DataTable("Foo"); 
    dt.Columns.Add(new DataColumn("AnotherColumn", typeof(MyData))); 
    dt.Rows.Add(new MyData("Row1C1", true)); 
    dt.Rows.Add(new MyData("Row2C1", false)); 
    dt.AcceptChanges(); 
    return dt; 
} 

bir sahiptir oluşturduk 2 özellikleri (bir dizge, bir Boole) sahip olan DataTable'ımı göstermek istediğim WPF DataGrid. Ancak tek yapmak istediğim, her bir hücrenin MyData nesnesine bağlı değerler içeren [TextBlock] [Düğme] 'i göstermek için nasıl oluşturulduğunu değiştirmek ve bu yüzden bir ton sorun yaşıyorum.

Benim XAML keresinde yüklenen do tüm TextBlock ve Düğme göstermek WPF DataGrid

dt = GetDummyData(); 
dataGrid1.ItemsSource = dt.DefaultView; 

DataTable bağlamak girişimi olduğunu, ancak onlar don Şimdi bu

<Window.Resources> 
    <ResourceDictionary> 
     <DataTemplate x:Key="MyDataTemplate" DataType="MyData"> 
      <StackPanel Orientation="Horizontal" > 
       <Button Background="Green" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,0,0" Content="{Binding Path=nameData}"></Button> 
       <TextBlock Background="Green" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5,0,0,0" Text="{Binding Path=nameData}"></TextBlock> 
      </StackPanel> 
     </DataTemplate> 
    </ResourceDictionary> 
</Window.Resources> 
<Grid> 
    <dg:DataGrid Grid.Row="1" ItemsSource="{Binding}" AutoGenerateColumns="True" 
       x:Name="dataGrid1" SelectionMode="Single" CanUserAddRows="False" 
       CanUserSortColumns="true" CanUserDeleteRows="False" AlternatingRowBackground="AliceBlue" 
       AutoGeneratingColumn="dataGrid1_AutoGeneratingColumn" /> 
</Grid> 

benziyor Bağlar, onları boş bırakır. Bunu nasıl düzeltebileceğine dair herhangi bir fikri olup olmadığını bana bildiren birileri olabilir. Bu basit olmalı, Microsoft'un bize inanmasına neden olduğu şey. AutoGenerating olayında Column.CellTemplate'u ayarlayıp hala bağlanmadım.

Lütfen yardım edin!

+0

Eğer DataGrid.DataContext olarak GetDummyData gelen datatable ayarı denediniz mi? – Ragepotato

+0

Zaten yaptı ve hala aynı şey. UIElements'de, bağlantısız oldukları anlaşılan hiçbir değişiklik yok. Kendi Column.CellTemplate'imi ayarlamak ve hala hiçbir şey ayarlamak için AutoGeneratingColumn olayı kullanmaya çalıştım. Başka fikirlerin var mı? Teşekkürler Teşekkürler –

+1

Bunu deneyin: [C# Excel'i Okuyun ve WPF DataGrid'de Göster] (http://www.codearsenal.net/2012/06/c-sharp-read-excel-and-show-in-wpf.html) –

cevap

14

Düzenleme: Aran Mulholland girişini yansıtacak şekilde Güncelleme

Görünüşe DataGrid her bir hücre için tüm DataRowView geçiyor (yorumunu bakınız). Bu yüzden ciltleme işe yaramıyor. DataTemplate, DataContext'un MyData türünde olmasını bekler, ancak bunun yerine DataRowView türünde olur. İstediğiniz DataContext almak için önerilen (biraz hack-ish) geçici çözüm, 'dan gerekli öğeyi çıkaracak bir özel DataGridTemplateColumn oluşturmaktır. kod aşağıda:

<Window x:Class="DataGridTemplateColumnSample.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:dg="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit" 
    Title="Window1" Height="300" Width="300"> 
    <Window.Resources> 
     <ResourceDictionary> 
      <DataTemplate x:Key="MyDataTemplate" DataType="DataRowView"> 
       <StackPanel Orientation="Horizontal"> 
        <Button Background="Green" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,0,0" Content="{Binding Path=nameData}"></Button> 
        <TextBlock Background="Green" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5,0,0,0" Text="{Binding Path=nameData}"></TextBlock> 
       </StackPanel> 
      </DataTemplate> 
     </ResourceDictionary> 
    </Window.Resources> 
    <Grid> 
     <dg:DataGrid Grid.Row="1" AutoGenerateColumns="True" x:Name="dataGrid1" SelectionMode="Single" 
        CanUserAddRows="False" CanUserSortColumns="true" CanUserDeleteRows="False" 
        AlternatingRowBackground="AliceBlue" AutoGeneratingColumn="dataGrid1_AutoGeneratingColumn" 
        ItemsSource="{Binding}" VirtualizingStackPanel.VirtualizationMode="Standard" /> 
    </Grid> 
</Window> 

using System.Data; 
using System.Windows; 
using Microsoft.Windows.Controls; 

namespace DataGridTemplateColumnSample 
{ 
    public partial class Window1 
    { 
     public Window1() 
     { 
      InitializeComponent(); 
      DataContext = GetDummyData().DefaultView; 
     } 

     private static DataTable GetDummyData() 
     { 
      var dt = new DataTable("Foo"); 
      dt.Columns.Add(new DataColumn("OneColumn", typeof(MyData))); 
      dt.Columns.Add(new DataColumn("AnotherColumn", typeof(MyData))); 
      dt.Rows.Add(new MyData("Row1C1", true), new MyData("Row1C2", true)); 
      dt.Rows.Add(new MyData("Row2C1", false), new MyData("Row2C2", true)); 
      dt.AcceptChanges(); 
      return dt; 
     } 

     private void dataGrid1_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e) 
     { 
      var column = new DataRowColumn(e.PropertyName); 
      column.Header = e.Column.Header; 
      column.CellTemplate = (DataTemplate)Resources["MyDataTemplate"]; 
      e.Column = column; 
     } 
    } 

    public class DataRowColumn : DataGridTemplateColumn 
    { 
     public DataRowColumn(string column) { ColumnName = column; } 
     public string ColumnName { get; private set; } 
     protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem) 
     { 
      var row = (DataRowView) dataItem; 
      var item = row[ColumnName]; 
      cell.DataContext = item; 
      var element = base.GenerateElement(cell, item); 
      return element; 
     } 
    } 

    public class MyData 
    { 
     public MyData(string name, bool data) { nameData = name; showData = data; } 
     public string nameData { get; set; } 
     public bool showData { get; set; } 
    } 
} 

Not: Bu yaklaşım, sadece konteyner sanallaştırma kapalıyken veya Standart modunda çalışması için görünür. VirtualizationMode Geri Dönüşüm'e ayarlanmışsa, şablon uygulanmaz.

+0

datagrid, hücreyi üretmek için her sütuna satırı iletir, bu standart davranıştır, kolondaki bağlanma hücre içeriğini tanımlar. Bence senin sorunun, her şeyi kodda yapıyorsun. Dinamik miktarlarda sütununuz var mı? eğer sütunlarınızı ve bağlarınızı sadece xaml olarak ayarlamıyorsanız. –

+1

Katılıyorum. Eğer bu benim projem olsaydı, bu şekilde şeyler yapmaktan kaçınmaya çalışırdım. Ne yazık ki, proje gereksinimleri (ör. Dinamik sütunlar) bazen işleri "temiz" bir şekilde yapmak için fazla yer bırakmaz. –

+0

Oh WOW. HARİKA. Çalışıyor .. Teşekkürler. Bu% 100 soruya cevap veriyor. Satır geçirdiğini ancak bu görünümde öğeye nasıl bağlanacağını anlayamadım. Çok teşekkürler. Maalesef, verileri önceden bilmeden bu şekilde işleri nasıl yapmaktan kaçınmayacağınızı anlamıyorum. Hangi stok sütunları ile çalışan esnek bir datagrid sahip olma amacını bozar. Veri türü olmayan stok türü olan örnekler için kendi DataTemplateColumn öğelerinizi tanımlamak, kutunun dışında çalışacağını düşünürdüm. Hayal edebilirim, sanırım. –

8

Bu iş parçacığını bulduğunuzda ve burada gösterilen kodla ilgili sorunla karşılaştıktan sonra, bu iş parçacığını MSDN'de çalıştırdım ve çok daha iyi çalışıyor! Gördüğüm kadarıyla sanallaştırma problemi yok.

http://social.msdn.microsoft.com/Forums/en/wpf/thread/8b2e94b7-3c44-4642-8acc-851de5285062

Kodu:

private void dataGrid1_AutoGeneratingColumn(object sender, Microsoft.Windows.Controls.DataGridAutoGeneratingColumnEventArgs e) 
{ 
    if (e.PropertyType == typeof(MyData)) 
    { 
     MyDataGridTemplateColumn col = new MyDataGridTemplateColumn(); 
     col.ColumnName = e.PropertyName; // so it knows from which column to get MyData 
     col.CellTemplate = (DataTemplate)FindResource("MyDataTemplate"); 
     e.Column = col; 
     e.Column.Header = e.PropertyName; 
    } 
} 

public class MyDataGridTemplateColumn : DataGridTemplateColumn 
{ 
    public string ColumnName 
    { 
     get; 
     set; 
    } 

    protected override System.Windows.FrameworkElement GenerateElement(DataGridCell cell, object dataItem) 
    { 
     // The DataGridTemplateColumn uses ContentPresenter with your DataTemplate. 
     ContentPresenter cp = (ContentPresenter)base.GenerateElement(cell, dataItem); 
     // Reset the Binding to the specific column. The default binding is to the DataRowView. 
     BindingOperations.SetBinding(cp, ContentPresenter.ContentProperty, new Binding(this.ColumnName)); 
     return cp; 
    } 
} 
İlgili konular