none
WPF Data Grid - How to hide the next column/row that is visible?

    Question

  • I'm using a WPF data grid to bind to an object (i.e. not a database). I have the horizontal alignment on Stretch. I currently have it within a Border, which is within a Grid.

    However when I run the application the DataGrid has a blank column and grid showing. That is say I have 5 columns & 5 rows, then there is a blank 6th column and row showing. See image:

    alt text

    Question - How can I get rid of these blank rows? Note that the contents of the DataGrid are populated programmatically (i.e. are not static).

    thanks

    Wednesday, September 29, 2010 9:39 AM

Answers

  • Yes, that could be ok. You can change the constructor to:
    public MainWindow()
    {
      InitializeComponent();
      TestDataGrid.ItemsSource = _testData;
      //// Test ONly
      var item = new TestItem { ProcessName = "Firefox", Total = 1234, Average = 123 };
      _testData.Add(item);
      item = new TestItem { ProcessName = "IE", Total = 2345, Average = 233 };
      _testData.Add(item);
      item = new TestItem { ProcessName = "Groupwise", Total = 3453, Average = 23 };
      _testData.Add(item);
    
      TestDataGrid.AutoGeneratingColumn += (s, e) =>
                         {
                           if (e.Column.Header.ToString() == "ProcessName")
                             e.Column.Width = new DataGridLength(1,
                                               DataGridLengthUnitType.
                                                 Star);
                         };
      
    }
    
    

     

    Bruno
    MVP Client Development - http://msmvps.com/blogs/bsonnino
    • Marked as answer by callagga Thursday, September 30, 2010 11:27 PM
    Thursday, September 30, 2010 10:14 PM

All replies

  • I'm using a WPF data grid to bind to an object (i.e. not a database). I have the horizontal alignment on Stretch. I currently have it within a Border, which is within a Grid.

    However when I run the application the DataGrid has a blank column and grid showing. That is say I have 5 columns & 5 rows, then there is a blank 6th column and row showing. See image:

    alt text

    Question - How can I get rid of these blank rows? Note that the contents of the DataGrid are populated programmatically (i.e. are not static).

    thanks

    • Merged by Kira Qian Thursday, September 30, 2010 8:27 AM duplicate
    Wednesday, September 29, 2010 9:35 AM
  • Did you try to set the CanUserAddRows property of the datagrid to False?

    Bruno


    MVP Client Development - http://msmvps.com/blogs/bsonnino
    • Proposed as answer by Xyzsamm Thursday, February 27, 2014 1:41 PM
    Wednesday, September 29, 2010 10:23 AM
  • Hello Callagga,

    For th last row , you can try to set <DataGrid  CanUserAddRows="False" />. This should be hide the last blank row.

    For the last column, try set it width of last column to Star, make is fill the available space.

    <wpftoolkit:DataGridTextColumn Header="Name" Width="*" />

     

    Hope this helps.


    Keep imporving.
    Yiling Lai. MVP (Visual C++ and Client App Dev)
    Wednesday, September 29, 2010 2:44 PM
  • that fixed the extra row below (thanks) however I still have the extra column on the right

    the issue with the extra column on the right seems to be to do with automatically setting column widths.  The DataGrid is actually setup (see XAML below) such that there is a GridSplitter just on it's right.  When I move the GridSplitter I note that the DataGrid columns don't resize automatically.  So overall the issue is both (a) on startup there is a partial extra column visible, and (b) after moving the GridSplitter they don't resize either.

    Any ideas on how to get this working?

    			<Grid>
    
    				<Grid.ColumnDefinitions>
    					<ColumnDefinition Width="Auto"/>
    					<ColumnDefinition Width="Auto"/>
    					<ColumnDefinition Width="*"/>
    				</Grid.ColumnDefinitions>
    
    				<Grid Grid.Column="0">
    					<Grid.RowDefinitions>
    						<RowDefinition Height="Auto"/>
    						<RowDefinition Height="Auto"/>
    						<RowDefinition Height="*"/>
    					</Grid.RowDefinitions>
    					<Label Content="Summary" Grid.Row="0" HorizontalAlignment="Center" />
    					<Grid Grid.Row="1">
    						<Grid.ColumnDefinitions>
    							<ColumnDefinition Width="*"/>
    							<ColumnDefinition Width="*"/>
    							<ColumnDefinition Width="*"/>
    							<ColumnDefinition Width="*"/>
    						</Grid.ColumnDefinitions>
    						<RadioButton IsChecked="{Binding Path=Period, Converter={StaticResource enumBooleanConverter}, ConverterParameter=AllTime}" Grid.Column="0">All Time</RadioButton>
    						<RadioButton IsChecked="{Binding Path=Period, Converter={StaticResource enumBooleanConverter}, ConverterParameter=Month}" Grid.Column="1">Month</RadioButton>
    						<RadioButton IsChecked="{Binding Path=Period, Converter={StaticResource enumBooleanConverter}, ConverterParameter=Week}" Grid.Column="2">Week</RadioButton>
    						<RadioButton IsChecked="{Binding Path=Period, Converter={StaticResource enumBooleanConverter}, ConverterParameter=Day}" Grid.Column="3">Day</RadioButton>
    					</Grid>
    					<Border Grid.Row="2">
    						<DataGrid Name="SummaryDataGrid" HorizontalGridLinesBrush="#FF726868" VerticalGridLinesBrush="#FF726868" AlternatingRowBackground="#FFD0F896" CanUserReorderColumns="False" CanUserResizeRows="False" CanUserAddRows="False" CanUserSortColumns="True" CanUserResizeColumns="False" ColumnWidth="Auto" />
    					</Border>
    
    				</Grid>
    
    
    				<GridSplitter HorizontalAlignment="Right" 
    				VerticalAlignment="Stretch" Grid.Column="1" ResizeBehavior="PreviousAndNext"
    				Width="5" Background="#FFBCBCBC"/>
    
    				<Grid Grid.Column="2" Name="RTChartGrid">
    					<-- CUT -->
    
    				</Grid>
    
    
    			</Grid>
    
    

    Wednesday, September 29, 2010 10:34 PM
  • You are setting the column widths as auto. If you set at least one column with as "*" (star), it will fill the empty space

    Bruno


    MVP Client Development - http://msmvps.com/blogs/bsonnino
    Wednesday, September 29, 2010 10:45 PM
  • oh - the problem is that I'm binding programmatically to an ObservableCollection, so the columns get created automatically in that sense.  I've tried in the VS designer to make the ColumnWidth ="*" however what then happens is that the first column then takes the entire width of the entire application window, so you don't even see the RTChartGrid section.

    Any ideas given this?  Is there a way to programmatically set the column widths manually, even though the values will come dynamically from the ObservableCollection?  e.g. so if I know there will be 3 columns in the collection how to set the 0th, 1st and 2nd?

     

    Code re how I'm binding:

     

    private ObservableCollection<SummaryItem> _summaryData = new ObservableCollection<SummaryItem>();
    
    SummaryDataGrid.ItemsSource = _summaryData;
    

     

     

     

    Thursday, September 30, 2010 3:20 AM
  • Hello

    we can register one event handler for auto generated column. When it is generated, we update its property to expected value.

    <DataGrid AutoGeneratingColumn="DG1_AutoGeneratingColumn"  />

    private void DG1_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
    {
        //Set properties on the columns during auto-generation
        switch (e.Column.Header.ToString())
        {
     .....
        }
    }

     

    Hope this helps.


    Keep imporving.
    Yiling Lai. MVP (Visual C++ and Client App Dev)
    Thursday, September 30, 2010 4:16 AM
  • One thing that you can do is set a column width to star on code. In the constructor, add:

    Loaded += (s,e) => datagrid.Columns[0].Width =

     

    new DataGridLength(1,DataGridLengthUnitType.Star);

    Bruno


    MVP Client Development - http://msmvps.com/blogs/bsonnino
    Thursday, September 30, 2010 8:53 AM
  • @Bruno - thanks however in the constructor this didn't seem to do anything.  I did try putting the width setting after the first records are programmatically added to the ObservableCollection however this caused the column to stretch across the whole width.  

    So got this:

    the image

    i.e. compared to before attempt of:

    the image

     

     


    Thursday, September 30, 2010 7:56 PM
  • @Yiling Lai - thanks but I didn't quite follow  :(

    Re "register one event handler for auto generated column" - how do you do this exactly?  By your code are you suggesting WPF will automatically register events if the names match <elementname>_<column_name>?  Just trying to guess how this might work...  Perhaps best if you assume I'm aware of WPF events but haven't used them much yet.  thanks


    Thursday, September 30, 2010 8:01 PM
  • Please, verify if you have set an explicit width for the datagrid. If you have, just remove the Width="xxx" from the datagrid

    Bruno


    MVP Client Development - http://msmvps.com/blogs/bsonnino
    Thursday, September 30, 2010 8:27 PM
  • no have haven't actually Bruno - nothing set programmatically, and the XAML is:

    <DataGrid Name="SummaryDataGrid"  HorizontalGridLinesBrush="#FF726868" VerticalGridLinesBrush="#FF726868" AlternatingRowBackground="#FFD0F896"  CanUserAddRows="False" CanUserSortColumns="True" />

    Perhaps I should extract a simpler lowest common denominator type example of the issue?

     

    Thursday, September 30, 2010 8:35 PM
  • this simple example seems to exhibit the same issue I'm having:

    the image

    <Window x:Class="MyInternetUsage.test_datagrid"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="test_datagrid" Height="300" Width="300">
      <Grid>
        <DataGrid Name="TestDataGrid" CanUserAddRows="False"/>
      </Grid>
    </Window>
    
    

     

      public partial class test_datagrid : Window
      {
    
        private ObservableCollection<TestItem> _testData = new ObservableCollection<TestItem>();
    
        public test_datagrid()
        {
          InitializeComponent();
    
          TestDataGrid.ItemsSource = _testData;
          //// Test ONly
          var item = new TestItem { ProcessName = "Firefox", Total = 1234, Average = 123 };
          _testData.Add(item);
          item = new TestItem { ProcessName = "IE", Total = 2345, Average = 233 };
          _testData.Add(item);
          item = new TestItem { ProcessName = "Groupwise", Total = 3453, Average = 23 };
          _testData.Add(item);
    
        }
      }
    
      public class TestItem : INotifyPropertyChanged
      {
        public event PropertyChangedEventHandler PropertyChanged;
    
        private string _processName;
        public string ProcessName
        {
          get { return _processName; }
          set
          {
            _processName = value;
            NotifyPropertyChanged("ProcessName");
          }
        }
    
        private long _total;
        public long Total
        {
          get { return _total; }
          set
          {
            _total = value;
            NotifyPropertyChanged("Total");
          }
        }
    
        private long _average;
        public long Average
        {
          get { return _average; }
          set
          {
            _average = value;
            NotifyPropertyChanged("Average");
          }
        }
    
        private void NotifyPropertyChanged(string propertyName)
        {
          if (PropertyChanged != null)
          {
            PropertyChanged(this, new PropertyChangedEventArgs((propertyName)));
          }
        }
    
      }
    

     

     

    Thursday, September 30, 2010 8:48 PM
  • Change the sample code to:
    public test_datagrid()
      {
       InitializeComponent();
    
       TestDataGrid.ItemsSource = _testData;
       //// Test ONly
       var item = new TestItem { ProcessName = "Firefox", Total = 1234, Average = 123 };
       _testData.Add(item);
       item = new TestItem { ProcessName = "IE", Total = 2345, Average = 233 };
       _testData.Add(item);
       item = new TestItem { ProcessName = "Groupwise", Total = 3453, Average = 23 };
       _testData.Add(item);
       Loaded += (s, e) => TestDataGrid.Columns[0].Width = new DataGridLength(1, DataGridLengthUnitType.Star);
      }
    
    

     

    Bruno


    MVP Client Development - http://msmvps.com/blogs/bsonnino
    Thursday, September 30, 2010 8:57 PM
  • oh yes - I see this works in the cutdown sample where I'm populating the test data during initialization - thanks

    if I do this in my app I get a ArgumentOutOfRangeException as no doubt the data isn't actually populated in the collection at that point (but rather later).  So I guess the Load event isn't the right point for what I want.   So, for better or worse, what I'm currently doing is loading the page with the databinding to the observableCollection in place, then later once data is available it starts adding items to the observableCollection.  So the datagrid wouldn't know how many columns there are until the first item in the observableCollection is in place.

    Would this imply I'd need to use the concept "register one event handler for auto generated column", that YiLing mentioned, but for which I'm not exactly sure how to setup?  

     

     


     

    Thursday, September 30, 2010 9:44 PM
  • Yes, that could be ok. You can change the constructor to:
    public MainWindow()
    {
      InitializeComponent();
      TestDataGrid.ItemsSource = _testData;
      //// Test ONly
      var item = new TestItem { ProcessName = "Firefox", Total = 1234, Average = 123 };
      _testData.Add(item);
      item = new TestItem { ProcessName = "IE", Total = 2345, Average = 233 };
      _testData.Add(item);
      item = new TestItem { ProcessName = "Groupwise", Total = 3453, Average = 23 };
      _testData.Add(item);
    
      TestDataGrid.AutoGeneratingColumn += (s, e) =>
                         {
                           if (e.Column.Header.ToString() == "ProcessName")
                             e.Column.Width = new DataGridLength(1,
                                               DataGridLengthUnitType.
                                                 Star);
                         };
      
    }
    
    

     

    Bruno
    MVP Client Development - http://msmvps.com/blogs/bsonnino
    • Marked as answer by callagga Thursday, September 30, 2010 11:27 PM
    Thursday, September 30, 2010 10:14 PM
  • thanks Bruno - that seems to work nicely

    Thursday, September 30, 2010 11:27 PM
  • For everyone who is having an extra column in the datagrid, please try Bruno Sonnino's solution above...it works!!!! thanks a lot Bruno

    Thursday, March 03, 2011 11:51 PM
  • any solution if you are NOT AutoGeneratingColum's
    Friday, May 06, 2011 3:02 PM
  • en la ultima columna establecer Width="*"
    (last column set Width="*")

    De esa forma la ultima columna ocupara el espacio restante del dataGrid

     

    <DataGrid Name="employeesDG" ItemsSource="{Binding}" 
             AutoGenerateColumns="False"
             HeadersVisibility="Column"
             CanUserAddRows="False"
             >
      <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding FirstName}"
                  Header="First Name"
                  IsReadOnly="True"
                  />
        <DataGridTextColumn Binding="{Binding LastName}"
                  Header="Last Name"
                  Width="*"
                  />
      </DataGrid.Columns>
    </DataGrid>
    

    Friday, May 13, 2011 2:25 AM
  • Hi Bruno,

    The fix suggested by you works , however if the grid has a grouping then the column at the end still appears when I have set the AutoGenerate Columns to True.

    Here is the styling that I use for Grouping, Could you kindly let me know if the  fix doesnot work because of the Grouping ?

     

     

    <Grid

    >

     

     

    <DataGrid Height="285" HorizontalAlignment="Left" Margin="12,14,0,0" Name="dataGrid1" VerticalAlignment="Top" CanUserResizeColumns="False" AutoGenerateColumns="True" AutoGeneratingColumn="DataGrid_AutoGeneratingColumn" Width="479" RowHeight="30" ColumnWidth

    ="100">

     

     

    <DataGrid.GroupStyle

    >

     

     

    <GroupStyle

    >

     

     

    <GroupStyle.HeaderTemplate

    >

     

     

    <DataTemplate

    >

     

     

    <StackPanel

    >

     

     

    <TextBlock Text="{Binding Path

    =Name}" />

     

     

    </StackPanel

    >

     

     

    </DataTemplate

    >

     

     

    </GroupStyle.HeaderTemplate

    >

     

     

    <GroupStyle.ContainerStyle

    >

     

     

    <Style TargetType="{x:Type GroupItem

    }">

     

     

    <Setter Property

    ="Template">

     

     

    <Setter.Value

    >

     

     

    <ControlTemplate TargetType="{x:Type GroupItem

    }">

     

     

    <Expander

    >

     

     

    <Expander.Header

    >

     

     

    <StackPanel Orientation

    ="Horizontal">

     

     

     

    <TextBlock Text="{Binding Path=Name}"

    />

     

     

    <TextBlock Text

    =" "/>

     

     

    <TextBlock Text="{Binding Path

    =ItemCount}"/>

     

     

    <TextBlock Text

    =" Items"/>

     

     

    </StackPanel

    >

     

     

    </Expander.Header

    >

     

     

    <ItemsPresenter

    />

     

     

    </Expander

    >

     

     

    </ControlTemplate

    >

     

     

    </Setter.Value

    >

     

     

    </Setter

    >

     

     

    </Style

    >

     

     

    </GroupStyle.ContainerStyle

    >

     

     

    </GroupStyle

    >

     

     

    </DataGrid.GroupStyle

    >

     

     

     

     

    </DataGrid

    >

     

     

     

    </Grid>

    and I apply Grouping with the following lines :

     

     

    ListCollectionView collection = new ListCollectionView

    (classList);

    collection.GroupDescriptions.Add(

     

    new PropertyGroupDescription("Name"));

    Thanking you in Advance,

    Best Regards,

    Rajendran

     
    Monday, November 07, 2011 6:45 PM
  • I also have similar issue and big pain is , I cant even change width of Column as width is fixed in our UI specs. If I use width ("*") then it will change width of last column automatically.

    Is there any other option like if I hide all ROW border from extra column space and make it look like nothing there.

    I need something like this

    Right now I have like this :

    Thanks

    Dee

    Friday, May 25, 2012 8:11 PM