WPF Toolkit datagrid displays extra column

Jun 9, 2009 at 5:11 PM

 Hi,

   I'm using the datagrid provided by the WPF Toolkit. Below I have pated a sample XAML that I use to create a simple datagrid with just one column. To my suprise event though I have just one column another column is automatically added. Anything I'm missing? Or, is it a bug?

 

<Page x:Class="DragDrop_ListBoxToDatagrid.Page1"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:toolkit="http://schemas.microsoft.com/wpf/2008/toolkit"

    xmlns:local="clr-namespace:DragDrop_ListBoxToDatagrid"

    Title="Page1">

    <StackPanel>        

        <ListBox local:DragAndDrop.DragEnabled="true" Name="lstCustNames">

            <ListBox.ItemTemplate>

                <DataTemplate>

                    <StackPanel>

                        <TextBlock Text="{Binding Name}" />                        

                    </StackPanel>

                </DataTemplate>

            </ListBox.ItemTemplate>

        </ListBox>

        <toolkit:DataGrid Name="dgCustNames"

                          AutoGenerateColumns="True"

                          local:DragAndDrop.DropEnabled="true">        

            <toolkit:DataGrid.Columns>

                <toolkit:DataGridTextColumn Header="Customer Name" 

                                        Binding="{Binding Name}" />    

            </toolkit:DataGrid.Columns>

        </toolkit:DataGrid>

    </StackPanel>

</Page>

 

Thanks,

Jithu

Coordinator
Jun 9, 2009 at 9:32 PM

Hi Jithu,

I think what's going on is that you have defined one column in the Columns collection and have also set AutoGenerateColumns to true, which will cause DataGrid to generate a column for each field in your data and append it to the end of the collection, and this is where the second column is coming from.  If you set AutoGenerateColumns to false, this should solve your problem. 

In general, there are three approaches which you could take when adding columns to your DataGrid:

1) Use autogeneration exclusively.  This is helpful for demo scenarios or prototyping when you just want to get up and running quickly, or when you have a smaller data set and you know you want to have a column in the grid to represent each field in the data.  If you just need to make some minor changes to the column collection as it's generated, you can hook into the autogeneration events to do things like cancel the creation of a certain column or change the column type of a certain column before it's created.

2) Define your columns explicitly.  Most production applications will probably go this route since it provides the most control over the columns collection.  In this case, you want to set AutoGenerateColumns to false and then define your columns either in the XAML or in the code behind.  This option is best suited for complex grids, especially if you're creating custom column types using template columns or want to set different width behaviors on each column.

3) Use a combination of the above.  This is the least common scenario, but might be useful if you want columns for each field in your data source plus some additional columns.  (This is similar to what you inadvertantly did above.)  In this case, you define the additional columns explicitly (in XAML or code) and these will be the first columns in the columns collection.  Then set AutoGenerateColumns to true, which will cause DataGrid to generate a column for each field in your data source and append them to the end of the columns collection.  This might be helpful if, for example, your data set has a bunch of number fields (like price and quantity) and you want to add an additional calculated column (like subtotal).  You can reorder the columns however you like at runtime using the DisplayIndex property.

Hope that helps!

Thanks,
Samantha

Jun 10, 2009 at 3:07 AM

Hi Samantha,

I tried to set AutoGenerateColumns to False, it still does not help. Also, if you take a look at the datagrid examples downloadable at WPF Toolkit site even those have a single column appended at the end. To add on, even the SouthRidge Labs samples have the same problem. That's why wanted to confirm if this is some kind of a miss?

 

Thanks,

Jithu

Coordinator
Jun 10, 2009 at 11:33 PM

Hi Jithu,

Oh, ok, it sounds like you are referring to the extra "filler" column that shows up at the end (with a blank header) to fill the remaining space if the DataGrid is wider than its total column width - is that correct?  If you want to hide this, you can set your last column (or in this case, your only column) to have * width, which will cause it to fill the remaining space and only display that one column.  Does that fix the problem you're seeing?  If not, please send a screenshot.

Thanks,
Samantha

Jun 11, 2009 at 4:12 PM

Hi Jithu,

If you want your column to have a fixed width and not fill the remaining space you can Template the ScrollViewer in the DataGrid and set the HorizontalAlignment="Left" on the DataGridColumnHeadersPresenter.  I then set the ItemsPanel for the DataGrid to a StackPanel and set its HorizontalAlignment="Left".

Hope this helps,

-LT

Aug 7, 2009 at 3:44 AM

I have a DataGrid defined as

<wpftoolkit:DataGrid
            x:Name="AccountsDataGrid"
            AutoGenerateColumns="False"
            ItemsSource="{Binding Path=Accounts}"
            ColumnReordered="DataGrid_ColumnReordered"
            SelectionUnit="FullRow"
            RowHeaderWidth="0"
            HorizontalAlignment="Stretch"
            VerticalAlignment="Stretch"
            >
            <wpftoolkit:DataGrid.Columns>
                <wpftoolkit:DataGridTextColumn Header="Account Id" Binding="{Binding Path=AccountId}" Width="Auto" />
                <wpftoolkit:DataGridTextColumn Header="Account Name" Binding="{Binding Path=AccountName}" Width="*" />
            </wpftoolkit:DataGrid.Columns>
        </wpftoolkit:DataGrid>

which on load looks great. the first column fits to the minimum width necessary to fit both the content and the header. the second column stretches to fill the rest of the width of the DataGrid (so I don't have a 3rd filler column). But if I try to reorder the columns, the AccountName column cannot be resized to a width less than what its width was before the reorder. So I added a handler on the ColumnReordered event, figuring I can just reset the column widths, but it doesn't seem to work. In fact, it shrinks the AccountId column to almost nothing, and the AccountName column still cannot be resized smaller.

 

private void DataGrid_ColumnReordered(object sender, Microsoft.Windows.Controls.DataGridColumnEventArgs e)
        {
            foreach (DataGridColumn column in AccountsDataGrid.Columns)
            {
                if (column.Equals(AccountsDataGrid.Columns.Last()))
                {
                    column.Width = new DataGridLength(1.0, DataGridLengthUnitType.Star);
                }
                else
                {
                    column.Width = new DataGridLength(1.0, DataGridLengthUnitType.Auto);
                }
            }
        }

 

Any thoughts?

Aug 7, 2009 at 7:30 AM

Hi

if u have fixed number of columns in datagrid then disable horizontalscroll bar and adjust the each column width

Sep 16, 2009 at 4:07 AM

Hi

Thank your suggestions above.

I set my column to have a fixed and set the HorizontalAlignment="Left" of Template the ScrollViewer in the DataGrid. It looks good.

But when I resize the column, decrease the column width, the last extra column appears again.

Is there any good way to avoid the last column in this situation?

Or what I want to do is handle the column change event to adjustify each column's with to fill the DataGrid's width. But I don't find column width change event.

Any thoughts?

Thanks very much

 

Sep 16, 2009 at 8:37 PM

Hi,

To avoid the last column situation I had to change my ItemsPanelTemplate for the Datagrid from the VirtualizingStackPanel usesd by default, to a regular StackPanel.  I had reported this behavior awhile ago but it hasn't been fixed yet.

-LT

Sep 17, 2009 at 3:58 AM

Sorry, I tried but I don't find anywhere or know how to set ItemsPanelTemplate for the Datagrid from the VirtualizingStackPanel StackPanel?

What I see is the

   <ItemsPanelTemplate x:Key="ItemsPanelTemplate1">
      <Custom:DataGridRowsPresenter IsItemsHost="True"/>
     </ItemsPanelTemplate>

Could you please give me more descriptions or an example?

Thanks

Sep 18, 2009 at 3:53 PM

that's where you would set it to a StackPanel.

What you see now:

<ItemsPanelTemplate x:Key="ItemsPanelTemplate1">
      <Custom:DataGridRowsPresenter IsItemsHost="True"/>
     </ItemsPanelTemplate>

What you change it to:

<ItemsPanelTemplate x:Key="ItemsPanelTemplate1">
      <StackPanel/>
     </ItemsPanelTemplate>

  Simple Example:

<dg:DataGrid x:Name="myDataGrid" HeadersVisibility="Column" AutoGenerateColumns="False" HorizontalScrollBarVisibility="Auto"
                  VerticalScrollBarVisibility="Auto" SelectionUnit="FullRow"  SelectionMode="Extended"
                  Style="{DynamicResource DataGridStyle1}" ItemsPanel="{DynamicResource ItemsPanelTemplate1}">
                <dg:DataGrid.Resources>
                    <!--<We remove the Virtualizing StackPanel from the DataGrid and replace with a standard StackPanel>-->
                    <ItemsPanelTemplate x:Key="ItemsPanelTemplate1">
                        <StackPanel HorizontalAlignment="Left"/>
                    </ItemsPanelTemplate>
                </dg:DataGrid.Resources>
</dg:DataGrid>

Set the ItemsPanel in the DataGrid to the corresponding ItemsPanelTemplate you wish to use.  This will get rid of the last "extra" column issue.

Hope this helps,
-LT

Sep 18, 2009 at 4:08 PM

If you replace DataGridRowsPresenter, be aware you might see some unexpected behavior. see http://blogs.msdn.com/vinsibal/archive/2008/08/14/wpf-datagrid-dissecting-the-visual-layout.aspx

Sep 18, 2009 at 4:57 PM

Correct, caution should always be taken when changing the itemsPanel but in this case I don't think it applies since they are both StackPanels.  I'm not sure from the diagram in the link what unexpected behavior would manifest since we're just replacing the "out of the box" VirtualizingStackPanel which is the one causing the unexpected behavior with a regular StackPanel which fixes the unexpected behavior.  Behavior of scrolling in the DataGrid works just fine.  The only trade off issue you may experience is if you are using very large amounts of data then you would want to use the VirtualizingStackPanel to increase performance.  Microsoft should fix the extra column issue so the work around doesn't have to be implemented but it's been working quite well for us.  For what it's worth, I haven't seen any issues in this scenario and I've been doing it this way since the CTP.

Cheers,
-LT

Sep 20, 2009 at 4:04 AM

Hi LT,

Thank your reply.

I tried your ways. to my surprise, this method makes none of the columnsdefined show. Every row is an empty row. Is anything else need to do?

Thanks very much

Dan

Sep 20, 2009 at 11:08 PM

Hi Dan,

Well, depending on how you were populating your DataGrid before, you may have to change AutoGenerateColumns="False" from my sample to AutoGenerateColumns="True".  I create mine dynamically in code behind so I set mine to false.  you may have been auto generating yours before.

Cheers,
-LT