.NET Forum / Languages / C# / February 2008
DataGridView footer
|
|
Thread rating:  |
Vanessa - 07 Jan 2008 17:44 GMT Hi all,
How can I display a footer in a DataGridView?
Thank you in advance, Vanessa
Nicholas Paldino [.NET/C# MVP] - 07 Jan 2008 17:58 GMT Vanessa,
You can't. You would have to custom paint the control and add the footer (no small task, by any means). You are better off with a third-party control that does this, or create your own control which will be displayed below the DataGridView.
 Signature - Nicholas Paldino [.NET/C# MVP] - mvp@spam.guard.caspershouse.com
> Hi all, > > How can I display a footer in a DataGridView? > > Thank you in advance, > Vanessa Vanessa - 07 Jan 2008 18:22 GMT Thank you!
Well, what I need is to sum some columns and put the total in the last row. If I add a row with the total, how can I prevent it to not participate in the sort?
Thanks in advance! Vanessa
> Vanessa, > [quoted text clipped - 9 lines] > > Thank you in advance, > > Vanessa Ignacio Machin ( .NET/ C# MVP ) - 07 Jan 2008 18:54 GMT Hi,
Why don't you create a control that contain a grid and a couple of textboxes under the correct column. Unless that you allow to reorder the columns in the grid it should be relatively simple to do.
 Signature Ignacio Machin http://www.laceupsolutions.com Mobile & warehouse Solutions.
> Thank you! > [quoted text clipped - 22 lines] >> > Thank you in advance, >> > Vanessa Vanessa - 07 Jan 2008 19:12 GMT Hello Ignacio,
Thank you for your answer. That is the exact problem, my datagridview could reorder and hide some columns.
What I need is something like this, but for windows form: http://www.eggheadcafe.com/tutorials/aspnet/cd3bb8d3-2608-487d-be33-1248becf3e16 /sumcolumn-custom-datagri.aspx
Thanks in advance, Vanessa
> Hi, > [quoted text clipped - 28 lines] > >> > Thank you in advance, > >> > Vanessa Marc Gravell - 08 Jan 2008 08:16 GMT How are you putting the data in the DataGridView? Are you binding to an existing list? If so, you might be able to influence the sort behavior by providing a custom sort implementation. If this is a DataTable it would be harder...
Marc
Vanessa - 08 Jan 2008 10:20 GMT Hi Marc!
I binding via dataview of a dataset table.
Thanks Vanessa
> How are you putting the data in the DataGridView? Are you binding to > an existing list? If so, you might be able to influence the sort > behavior by providing a custom sort implementation. If this is a > DataTable it would be harder... > > Marc Marc Gravell - 08 Jan 2008 11:13 GMT Damn; that makes this a pain... I'll see if I can come up with something later? (busy at the mo...)
Marc
Vanessa - 08 Jan 2008 11:44 GMT Hi Marc,
Thank you and I will wait for your help!
Vanessa
> Damn; that makes this a pain... I'll see if I can come up with > something later? (busy at the mo...) > > Marc Marc Gravell - 08 Jan 2008 12:50 GMT I got something working by having a dummy (hidden) column to indicate whether it is a footer row or not (well, actually it just uses a hidden preliminary sort, so it would also work for headers etc)... It works by hiding an extra (first) sort in IBindingList and IBindingListView... it has to be hidden for the reversal to work properly. here is the usage example; I'll post the implementation (CustomDataView) in a second post (it's a bit long... but most of it was auto-generated)
static void Main() { Application.EnableVisualStyles(); // declare table DataTable dt = new DataTable("Test"); dt.Columns.Add("IsFooter", typeof(bool)); dt.Columns.Add("Caption", typeof(string)); dt.Columns.Add("Value", typeof(int)); // fill with some random data Random rand = new Random(); int sum = 0; for (int i = 0; i < 20; i++) { int val = rand.Next(50); dt.Rows.Add(false, "Row " + i.ToString(), val); sum += val; } // add footer row dt.Rows.Add(true, "Total", sum);
// display using(Form form = new Form()) using (DataGridView grid = new DataGridView()) { grid.Dock = DockStyle.Fill; grid.AllowUserToAddRows = false; form.Controls.Add(grid); grid.DataSource = new CustomDataView(dt.DefaultView, "IsFooter", ListSortDirection.Ascending); grid.Columns[0].Visible = false; Application.Run(form); } }
Marc Gravell - 08 Jan 2008 12:51 GMT public class CustomDataView : IBindingListView, IBindingList, IList, ICollection, IEnumerable, ITypedList, ISupportInitializeNotification, ISupportInitialize { readonly DataView parent; readonly ListSortDescription fixedSort; public CustomDataView(DataView parent, string sortProperty, ListSortDirection sortDirection) { if (parent == null) throw new ArgumentNullException(); this.parent = parent; if (!SupportsSorting || !SupportsAdvancedSorting) { throw new InvalidOperationException("Advanced sorting is required"); } fixedSort = new ListSortDescription(GetItemProperties(null)[sortProperty], sortDirection); RemoveSort(); }
#region IBindingListView Members
void IBindingListView.ApplySort(ListSortDescriptionCollection sorts) { ListSortDescription[] sortArray = new ListSortDescription[sorts.Count + 1]; sorts.CopyTo(sortArray, 1); sortArray[0] = fixedSort; ApplySort(sortArray); }
string IBindingListView.Filter { get { return ((IBindingListView)parent).Filter; } set { ((IBindingListView)parent).Filter = value; } }
void IBindingListView.RemoveFilter() { ((IBindingListView)parent).RemoveFilter(); }
ListSortDescriptionCollection IBindingListView.SortDescriptions { get { ListSortDescriptionCollection sorts = ((IBindingListView)parent).SortDescriptions; if(sorts == null || sorts.Count == 0) return sorts; ListSortDescription[] sortArray = new ListSortDescription[sorts.Count - 1]; for (int i = 1; i < sorts.Count; i++) { sortArray[i - 1] = sorts[i]; } return new ListSortDescriptionCollection(sortArray); } }
public bool SupportsAdvancedSorting { get { return ((IBindingListView)parent).SupportsAdvancedSorting; } }
bool IBindingListView.SupportsFiltering { get { return ((IBindingListView)parent).SupportsFiltering; } }
#endregion
#region IBindingList Members
void IBindingList.AddIndex(PropertyDescriptor property) { ((IBindingList)parent).AddIndex(property); }
object IBindingList.AddNew() { return ((IBindingList)parent).AddNew(); }
bool IBindingList.AllowEdit { get { return ((IBindingList)parent).AllowEdit; } }
bool IBindingList.AllowNew { get { return ((IBindingList)parent).AllowNew; } }
bool IBindingList.AllowRemove { get { return ((IBindingList)parent).AllowRemove; } }
void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction) { ApplySort(fixedSort, new ListSortDescription(property, direction)); } void ApplySort(params ListSortDescription[] sorts) { ((IBindingListView)parent).ApplySort(new ListSortDescriptionCollection(sorts)); }
int IBindingList.Find(PropertyDescriptor property, object key) { return ((IBindingList)parent).Find(property, key); }
public bool IsSorted { get { return ((IBindingList)parent).IsSorted && ((IBindingListView)parent).SortDescriptions.Count > 1; } }
event ListChangedEventHandler IBindingList.ListChanged { add { ((IBindingList)parent).ListChanged += value; } remove { ((IBindingList)parent).ListChanged -= value; } }
void IBindingList.RemoveIndex(PropertyDescriptor property) { ((IBindingList)parent).RemoveIndex(property); }
public void RemoveSort() { ApplySort(fixedSort); }
ListSortDirection IBindingList.SortDirection { get { if (IsSorted) { return ((IBindingListView)parent).SortDescriptions[1].SortDirection; } else { return ListSortDirection.Ascending; } } }
PropertyDescriptor IBindingList.SortProperty { get { if (IsSorted) { return ((IBindingListView)parent).SortDescriptions[1].PropertyDescriptor; } else { return null; } } }
bool IBindingList.SupportsChangeNotification { get { return ((IBindingList)parent).SupportsChangeNotification; } }
bool IBindingList.SupportsSearching { get { return ((IBindingList)parent).SupportsSearching; } }
public bool SupportsSorting { get { return ((IBindingList)parent).SupportsSorting; } }
#endregion
#region IList Members
int System.Collections.IList.Add(object value) { return ((IList)parent).Add(value); }
void System.Collections.IList.Clear() { ((IList)parent).Clear(); }
bool System.Collections.IList.Contains(object value) { return ((IList)parent).Contains(value); }
int System.Collections.IList.IndexOf(object value) { return ((IList)parent).IndexOf(value); }
void System.Collections.IList.Insert(int index, object value) { ((IList)parent).Insert(index, value); }
bool System.Collections.IList.IsFixedSize { get { return ((IList)parent).IsFixedSize; } }
bool System.Collections.IList.IsReadOnly { get { return ((IList)parent).IsReadOnly; } }
void System.Collections.IList.Remove(object value) { ((IList)parent).Remove(value); }
void System.Collections.IList.RemoveAt(int index) { ((IList)parent).RemoveAt(index); }
object System.Collections.IList.this[int index] { get { return ((IList)parent)[index]; } set { ((IList)parent)[index] = value; } }
#endregion
#region ICollection Members
void System.Collections.ICollection.CopyTo(Array array, int index) { ((ICollection)parent).CopyTo(array, index); }
int System.Collections.ICollection.Count { get { return ((ICollection)parent).Count; } }
bool System.Collections.ICollection.IsSynchronized { get { return ((ICollection)parent).IsSynchronized; } }
object System.Collections.ICollection.SyncRoot { get { return ((ICollection)parent).SyncRoot; } }
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return ((IEnumerable)parent).GetEnumerator(); }
#endregion
#region ITypedList Members
PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors) { return GetItemProperties(listAccessors); } private PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors) { return ((ITypedList)parent).GetItemProperties(listAccessors); }
string ITypedList.GetListName(PropertyDescriptor[] listAccessors) { return ((ITypedList)parent).GetListName(listAccessors); }
#endregion
#region ISupportInitializeNotification Members
event EventHandler ISupportInitializeNotification.Initialized { add { ((ISupportInitializeNotification)parent).Initialized += value; } remove { ((ISupportInitializeNotification)parent).Initialized -= value; } }
bool ISupportInitializeNotification.IsInitialized { get { return ((ISupportInitializeNotification)parent).IsInitialized; } }
#endregion
#region ISupportInitialize Members
void ISupportInitialize.BeginInit() { ((ISupportInitialize)parent).BeginInit(); }
void ISupportInitialize.EndInit() { ((ISupportInitialize)parent).EndInit(); }
#endregion }
Vanessa - 08 Jan 2008 13:45 GMT Thank you very much! It worked in a sample, so I will adapt it into my project. Vanessa
> public class CustomDataView : IBindingListView, IBindingList, IList, > ICollection, IEnumerable, ITypedList, ISupportInitializeNotification, [quoted text clipped - 286 lines] > #endregion > } Marc Gravell - 08 Jan 2008 14:01 GMT > Thank you very much! It worked in a sample, so I will adapt it into > my project. You're welcome; if you get any problems, post back ;-p
Best of luck, Marc
Greg - 08 Jan 2008 06:08 GMT > Hi all, > > How can I display a footer in a DataGridView? > > Thank you in advance, > Vanessa Painting it is your best bet. I extended a ListView control to have a footer and header. The footer was a summation of records as well as the controls to allow for paging large records.
cheers Greg
Vanessa - 08 Jan 2008 10:21 GMT Hi Greg!
Do you have an example on how can I do this?
Thanks Vanessa
> > Hi all, > > [quoted text clipped - 9 lines] > cheers > Greg gajendra.baragur@softappsit.com - 25 Feb 2008 14:34 GMT Hi Marc Gravell, Even i have similar problem what you have explained earlier for the above thread.
I just want to clarify my doubt regarding IBindingListView. In my application i have used BindingSource that i have binded to a DataGridView that, BindingSource i have associated to a class with four properties. I'm able to display those property contents in the DataGridView but unable to filter it. I have 50 records in the BindingSource in that i need to filter only those records starting from the Itemid greater than 10 and lesser than or equal to 30. I have tried the below methods.... 1) itemsBindingSource.Filter = "Itemid > =" + 10 + " and Itemid <=" + 30; 2) temsBindingSource.Filter="Slno between " + startno + " and " + Endno; (This is what you have suggested in the last discussion) I tried itemsBindingSource.SupportsFiltering property eventhough it always returns false.
Actually i'm implementing the above code for DataGridView paging, so that i can display few records using filter in a single page.
Thanks in advance,
Gajendra
Marc Gravell - 25 Feb 2008 14:51 GMT I don't think it would be simple to apply paging using a filter; in particular, the code for adding/removing items (at the bottom of the DataGridView) would be a real pain. As it happens I do have a (predicate-oriented) filtered-list implementation up my sleeve, but I don't think it is a good fit for what you are doing...
Being pragmatic, for paging, would it not be easier to simply copy the page that you want from your original list into the data-bound list?
> (This is what you have suggested in the last discussion) Did I? I don't remember that, and can't see it in the archive...
For info, this discussion was really about sorting, not filtering; they are very different beasts...
If you are paging over a very large result, consider also "virtual mode".
Marc
Gajendra - 26 Feb 2008 07:31 GMT Hi Marc,
Thanx for your reply...
Basically I have an example of datagridview paging using dataset where he used to show the records in pages through filter condition. The following line is used for filter condition in that example.
bindingSource1.Filter = "RecordID >= " + RecordID1 + " and RecordID <= " + RecordID2; GridView1.DataSource = bindingSource1;
For your kind reference follow the link which has the above code.. http://www.codeproject.com/KB/miscctrl/Pagable_DatagridView.aspx
The project which includes the above two statements is working fine & the supportsFiltering is also returning true. So now I want to implement the same through BindingSource using collections. Hence I have binded to a class which has four properties. The binding part & displaying in gridview is working fine.Now what I want exactly is, I want to display only 100 records in first page among 500 records. So i need to filter for a certain range so that it fulfils my requirement.
Hope you understood my requirement. I am struggling for this part from past few days, so if u please help me in this regard as soon as possible, it will be very much appreciable.
Thanks once again...
>I don't think it would be simple to apply paging using a filter; in >particular, the code for adding/removing items (at the bottom of the [quoted text clipped - 15 lines] > >Marc Marc Gravell - 26 Feb 2008 08:08 GMT I understand whay you are trying to do... but using a filter is probably not going to be your best option here. The point is that BindingList<T> etc don't support filter "out of the box". I have a filtering example, but it is 556 LOC (mainly due to the complexities of dealing with full property notification over bound data. And this is the *simple* version that uses a predicate filter (not a parser).
Quite simply - I think that a filtered list would be the wrong answer to your problem; all you need is paging...
You don't indicate whay .NET version you are using - if you have 3.5 this would be even easier (Skip() and Take()), but since paging is so simple how about simply something like (note most of this code is the example; the list itself is very simple):
using System; using System.Collections.Generic; using System.ComponentModel; using System.Windows.Forms;
class DemoData { private int value1; private double value2; [DisplayName("Value 1")] public int Value1 { get { return value1; } set { value1 = value; } } [DisplayName("Value 2")] public double Value2 { get { return value2; } set { value2 = value; } } } static class Program {
[STAThread] static void Main() { List<DemoData> data = new List<DemoData>(); Random rand = new Random(); for (int i = 0; i < 10000; i++) { DemoData dd = new DemoData(); dd.Value1 = rand.Next(500); dd.Value2 = rand.NextDouble() * 500; data.Add(dd); }
Application.EnableVisualStyles(); using(Form form = new Form()) using (DataGridView view = new DataGridView()) using (Button next = new Button()) using (Button prev = new Button()) { PagedList<DemoData> paged = new PagedList<DemoData>(data, 0, 50); next.Click += delegate { paged.PageIndex += 1; }; prev.Click += delegate { paged.PageIndex -= 1; }; view.Dock = DockStyle.Fill; view.DataSource = paged; next.Dock = prev.Dock = DockStyle.Bottom; next.Text = ">"; prev.Text = "<"; form.Controls.AddRange(new Control[] { view, next, prev }); Application.Run(form); } } } class PagedList<T> : BindingList<T> { private readonly IList<T> source; public PagedList(IList<T> source) { if (source == null) throw new ArgumentNullException("source"); this.source = source; SetPage(0, source.Count); } public PagedList(IList<T> source, int pageIndex, int pageSize) { if (source == null) throw new ArgumentNullException("source"); this.source = source; SetPage(pageIndex, pageSize); } private int pageIndex, pageSize; public int PageIndex { get { return pageIndex; } set { SetPage(value, PageSize); } } public int PageSize { get { return pageSize; } set { SetPage(PageIndex, value); } } public void SetPage(int pageIndex, int pageSize) { if (pageIndex < 0) throw new ArgumentOutOfRangeException("pageIndex"); if (pageSize <= 0) throw new ArgumentOutOfRangeException("pageSize"); this.pageIndex = pageIndex; this.pageSize = pageSize;
bool wasRaising = RaiseListChangedEvents; RaiseListChangedEvents = false; try { Clear(); int start = pageSize * pageIndex, end = start + pageSize; if (end > source.Count) end = source.Count; for (int i = start; i < end; i++) { Add(source[i]); } } finally { RaiseListChangedEvents = wasRaising; ResetBindings(); }
} }
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|