DataGridView - BindingSource Help Needed

T

Tom

I have populated a List with objects containing FileInfo. This List is
bound to a DataGridView and the contents *are* visible within the
DataGridView control. When I click within the DataGridView I get the
following error >>

Index -1 does not have a value.

Perhaps I simply need to understand how to set the index correctly? Or
maybe I need to assign values to the row & column headers? Or any of a
host of typical *newbie* mistakes.

Please point me in the right direction.

Thanks !!

-- Tom


// Primary Statements Involving DataGridView & Data Classes >>

public class FilePicker2 : Form
{
DataGridView grid;
BindingSource bindsrc = new BindingSource();
[STAThread]
public static void Main()
{
Application.EnableVisualStyles();
Application.Run(new FilePicker2());
}

public FilePicker2()
{
bindsrc.DataSource = new Directory();
bindsrc.DataMember = "FilesInfo";

grid = new DataGridView();
grid.Parent = split1.Panel2;
grid.AutoSize = true;
grid.Dock = DockStyle.Fill;

grid.AutoGenerateColumns = false; // Columns Manually Added Below
grid.DataSource = bindsrc;

DataGridViewTextBoxColumn colText = new DataGridViewTextBoxColumn();
colText.DataPropertyName = "Name";
colText.HeaderText = "Name";
grid.Columns.Add(colText);

colText = new DataGridViewTextBoxColumn();
colText.DataPropertyName = "Ext";
colText.HeaderText = "Ext.";
grid.Columns.Add(colText);

colText = new DataGridViewTextBoxColumn();
colText.DataPropertyName = "Size";
colText.HeaderText = "Size";
colText.DefaultCellStyle.Alignment =
DataGridViewContenetAlignment.MiddleRight;
grid.Columns.Add(colText);

colText = new DataGridViewTextBoxColumn();
colText.DataPropertyName = "ModifyTime";
colText.HeaderText = "Date & Time";
grid.Columns.Add(colText);

grid.BorderStyle = BorderStyle.None;
grid.CellBorderStyle = DataGridViewCellBorderStyle.None;
grid.RowHeadersVisible = false;
grid.ScrollBars = ScrollBars.Vertical; // << Not Working
grid.AllowUserToOrderColumns = true;
grid.ReadOnly = true;
grid.AllowUserToAddRows = false;
grid.AllowUserToAddColumns = false;
grid.SelectionMode = DataGridViewSelectionMode.FullRowSelect;

grid.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells);

} // End of Constructor


// The following is called upon directory selection in a TreeView

public void Fill_dirList(string path)
{
DirectoryInfo dirinfo = new DirectoryInfo(path);
Directory.filelist.Clear();
foreach (FileInfo file in dirinfo.GetFiles())
{
FileDetail temp = new FileDetail(file);

Directory.filelist.Add(temp); // << Filling the List
// That Is Bound to
// the DataGridView
}
}

} // public class FilePicker2 : Form


// Partial Class Information >>

public class Directory
{
public static List<FileDetail> filelist = new List<FileDetail>();

public List<FileDetail> FilesInfo
{
set { filelist = value; } // << No Change When Commented Out
get ( return filelist: }
}
}

// ###############################################
public class FileDetail
{
private string name, ext, size, modifytime;

public FileDetail(FileInfo fileInfo)
{
this.name = fileInfo.Name;
this.ext = fileInfo.Extension:
this.size = fileInfo.Length.ToString());
this.modifyTime =
fileInfo.LastWriteTime.ToString("yyy'-'MM'-'dd' HH':'mm");
}

public string Name { get { return this.name; } }
public string Ext { get { return this.ext; } }
public string Size { get { return this.size; } }
public string ModifyTime { get { return this.modifyTime; } }
}
 
M

Marc Gravell

First off... the code clearly contains a lot of simple code typos that
make it a nuicance to investigate... why not just paste verbatim (or
check it in the compiler first?)

Anyways... gripe over...

The problem is that List<T> does not support change notification
(IBindingList), which means that when the contents change the grid has
no way of knowing. Then when it goes to get data (that was there last
time it looked) it has vanished.

The simplest (and on this occasion, most efficient) fix here is to
tell the grid that you have done something interesting:

bindsrc.ResetBindings(false);

Another potential answer is to use BindingList<T> in place of List<T>,
since this supports change notifications; as an aside, note that using
a static collection in this way has a number of associated threading
risks.

Finally, to avoid lots of events while rebuilding a BindingList<T>,
you might want to either unbind the grid during updates, or suspend
notifications:

public static void SetContents(IEnumerable<FileDetail> details)
{
if (details == null) throw new ArgumentNullException();
bool priorChatty = filelist.RaiseListChangedEvents;
filelist.RaiseListChangedEvents = false;
try
{
filelist.Clear();
foreach (FileDetail detail in details)
{
filelist.Add(detail);
}
}
finally
{
filelist.RaiseListChangedEvents = priorChatty;
filelist.ResetBindings();
}
}

Marc
 
T

Tom

Thank you Marc --

Wow! Excellent block of code! I appreciate your suggestions greatly.
There are many aspects in your coding block that improve what I was
attempting. I'm still absorbing it ... but it's darn near magical how
concise and powerful it is with its usage of exceptions and types of
which I was unfamiliar.

My apologies for the typos ... I seldom see large blocks of code
posted in here and know what I provided would not compile. I wanted to
show concisely my problem areas without the TreeView code, includes,
SplitterPanels, Icon resources, etc. I probably need to realize
experts can handle large blocks with ease and treat code as if it
would get pasted into VS. My attempt to focus the coding into a more
easily read and condensed format was a poor choice on my part.

I think my learning difficulties in part stem from Petzold's giant
steps. He goes from manually unbound DataGridView to bound with XML
Serialization I/O in a blink of the eye (Chapter 6, Windows Forms). I
am not being critical of Petzold. At my skill level I was simply
unable to connect the dots. What I needed was something in between and
I was unaware of the type BindingList<T> that seems to be a "perfect"
fit for my task.

Again, my many thanks to Marc for understanding my task better than
myself and getting me unstuck so that I can continue the learning
adventure.

-- Tom
 
M

Marc Gravell

Thank you Marc

No problem; and to be fair your code was sufficient to express both
your intent and the issue, which is what really matters. If you get
stuck, please come back ;-p

Best of luck,

Marc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top