views:

740

answers:

0

Hello there! I'm hoping that one of your WPF/DataGrid/Binding gurus can help me out here. I've done a bunch of searching on the subject and while datagrid binding tutorials and tips are plentiful (and I feel like I've read every single one of them), I'm still stumped on this piece.

My setup is this: I have an application that has a bunch of different DataTables, and I'm trying to share 1 WPF DataGrid to view/edit them one at a time (user selects which one they want to view). The DataTables are completely dynamic and there is no way for me to know at compile time the properties like columns, column types, column headers, column display order, sort order, and so on.

This part is working great.

However, now I'm trying to customize the individual DataGridTextColumn cells by way of AutoGeneratingColumn to allow for field templates so I can have cell templates, suggestions, and whatever else. I am doing this by adding some DataTemplates to my grid and selecting which one I need in the AutoGeneratingColumn event based off of parameters in my class.

The problem I'm having is binding the cell to the data, and I feel like if I just get the Text="{Binding .... }" part right in my / this whole thing will fall into place. Like I said though, my DataTables are dynamic and I have no idea at compile time what I need to bind to.

Here's some code:

<toolkit:DataGrid Name="dgNote" ItemsSource="{Binding}" 
                                      SelectionMode="Single"
                                      SelectionUnit="CellOrRowHeader"
                                      LayoutUpdated="dgNote_LayoutUpdated"
                                      Style="{StaticResource DataGridStyle}"
                                      MouseRightButtonUp="dgNote_MouseRightButtonUp"
                                      ContextMenuOpening="ContextMenu_Opening" 
                                      ColumnHeaderStyle="{StaticResource DefaultColumnHeaderStyle}" RowHeaderWidth="15"
                                      RowHeaderStyle="{StaticResource DefaultRowHeaderStyle}" CanUserAddRows="True"
                                      ColumnDisplayIndexChanged="dgNote_ColumnDisplayIndexChanged" AutoGenerateColumns="True"
                                      CellStyle="{StaticResource DataGridCellStyle}"
                                      Sorting="dgNote_Sorting"
                                      CellEditEnding="dgNote_CellEditEnding"
                                      AutoGeneratingColumn="dgNote_AutoGeneratingColumn"
                                      AutoGeneratedColumns="dgNote_AutoGeneratedColumns"
                                      >
                        <toolkit:DataGrid.Resources>
                            <ObjectDataProvider x:Key="columnDataProvider" MethodName="GetCellContent"/>
                            <DataTemplate x:Key="DataGridTextColumn" DataType="DataGridCell">
                                <StackPanel Name="sp">
                                    <TextBlock x:Name="tbContent" Text="{Binding /}" VerticalAlignment="Top" HorizontalAlignment="Stretch" TextWrapping="Wrap" />
                                </StackPanel>
                            </DataTemplate>
                            <DataTemplate x:Key="DataGridTextColumnEditing" DataType="DataGridCell">
                                <StackPanel>
                                    <TextBox Name="tbContentEditing" Text="{Binding Path=[0]}" VerticalAlignment="Top" HorizontalAlignment="Stretch" TextWrapping="Wrap" TextChanged="TextBox_TextChanged" />
                                    <ListBox Name="listBox1" Visibility="Hidden" ItemsSource="{Binding}" HorizontalAlignment="Stretch" Focusable="False"/>
                                </StackPanel>
                            </DataTemplate>
                        </toolkit:DataGrid.Resources>

and the code behind (with some of my failed attempts commented out):

        private void dgNote_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
    {
        // wrap text cells.
        if (e.Column is DataGridTextColumn)
        {
            //((DataGridTextColumn)e.Column).ElementStyle = (Style)Resources["dgTextColumnStyle"];
            DataGridTemplateColumn col = new DataGridTemplateColumn();
            col.CellTemplate = (DataTemplate)dgNote.FindResource("DataGridTextColumn");
            if (col.CellTemplate.VisualTree != null)
            {
                Console.WriteLine("hey!");
            }
            col.CellEditingTemplate = (DataTemplate)dgNote.FindResource("DataGridTextColumn");
            col.CellStyle = (Style)Resources["dgTextColumnStyle"];

            //TextBlock tb = ((TextBlock)col.CellTemplate.FindName("tbContent", col.CellTemplate.VisualTree));
            //tb.DataContext = new Binding("Value");
            col.Header = e.PropertyName;

            ObjectDataProvider columnResource = (ObjectDataProvider)dgNote.FindResource("columnDataProvider");

            //if (columnResource != null) columnResource.ObjectType = typeof(System.Data.DataColumn);
            if (columnResource != null)
            {
                //columnResource.ObjectType = typeof(System.Data.DataColumn);
                //columnResource.ObjectInstance = ((TableNote)tvNotes.SelectedItem.Note).Table.Columns[e.PropertyName];
            }
            //col.SetValue(ContentProperty, ((TableNote)tvNotes.SelectedItem.Note).Table.Columns[e.PropertyName]);

            e.Column = col;

            //((DataGridTextColumn)e.Column).Binding = new Binding(e.PropertyName);
        }
    }

One thing that's weird to me is the column header isn't getting populated with the PropertyName above. Stepping through the code I can see it being set to the correct value, but it just doesn't show up in the grid afterwords. The two issues might be related?

I've tried all sorts of things and based on my reading I think I'm on the right path by setting an ObjectDataProvider and binding to that in the XAML, then setting the ObjectDataProvider in my code. But heck if I can figure out the right syntax.

The closest I came to getting something to show up is setting the Text="{Binding Path=[0]}" in the , in which case all my fields only show the string in the first cell of the particular column (but not taking DisplayIndex into consideration) for the current row. The other time is if I set Text="{Binding}" in the , but then I get "System.Data.DataRowView" in all my fields. I understand why that's happening, but I'm not sure how to fix it.

With anything else I try I either get empty fields or an exception.

Anything here throw some red flags?