I'm working on a contact management application, and need a hand with one
aspect...
Here's what I want to create:
------------------------------------
A form split into two parts. There is a datagrid on the left side that lists
names and perhaps a couple of other key fields. The user can click on a
record in the datagrid, which should automatically pull up details on that
record in the various text boxes and other controls on the right side of the
form.
The datagrid on the left side of the form should also be filterable. A
filter is entered from a textbox above the datagrid. For example,
if the user types "An" in the textbox, the datagrid only shows names
that start with "An" (e.g. "Anderson", "Anthony", "Anzar").
So I want 2 features:
1) a datagrid that is used as a record selector, and
2) a datagrid that may be filtered.
Here's my problem
------------------------------------
I can get either feature #1 or feature #2 to work, but not both at the same
time.
To get feature #1 to work, I bind the datagrid to my "contact" table,
and then I bind my various textboxes and other controls to individual fields
within the "contact" table. And then like magic,
when I select a record in the datagrid on the left side of the form,
that record is pulled up in the controls on the rigth side of the form.
I can also get feature #1 to work by putting my DataSet into a
DataViewManager,
and then binding my datagrid and my other controls to that.
To get feature #2 to work, I create a DataView object based on my "contact"
table, and then bind the datagrid to that DataView object. When I change the
RowFilter property, the grid changes just as I want. But when I select a
record in the datagrid, nothing happens on the right side of the form.
My own experiments
------------------------------------
I've tried experimenting with performing filters on the "contact" table's
DefaultView, but changing the RowFilter property doesn't seem to do
anything.
I've tried using a DataViewManager object for filtering without success (I
don't really
understand them completely).
Other notes
------------------------------------
1) I don't want all the fields from "contacts" appearing in the datagrid, so
I use a DataGridTableStyle to customize how stuff appears in the datagrid. I
don't think this effects anything adversely.
2) The datagrid, along with a couple of other controls, is tucked into a
User Control, which I've called Navigator. I don't think this effects
anything adversely either.
3) I'm using SharpDevelop, not Visual Studio (yet), so I do databinding
programmatically, not through the form designer.
Request for help
------------------------------------
I'm very experienced with C but new to C# and .Net (and I really like it). I
could really use advise on the best way to accomplish this task, but I also
wish to solicit advice on proper coding style and better program structure.
My code (without indents) from my Navigator user control, version 1
----------------------------------------------------------------------
// In this version, the filtering works, but the DataGrid stops acting as a
// record selector.
// grdPerson is the name of my DataGrid.
// My user control is called Navigator.
// The following code is used to set up the databinding.
DataView dataView;
public void SetDataBinding(DataView dataSource)
{
dataView = dataSource;
DoBinding();
}
public void SetDataBinding(DataTable dataSource, string sortByField)
{
dataView = new DataView(dataSource);
dataView.AllowDelete = false;
dataView.AllowNew = false;
dataView.Sort = sortByField + "ASC";
DoBinding();
}
void DoBinding()
{
const int NameColumnWidth = 130;
grdPerson.DataSource = dataView;
DataGridTableStyle tableStyle = new DataGridTableStyle();
tableStyle.MappingName = dataView.Table.TableName;
tableStyle.ReadOnly = true;
tableStyle.RowHeadersVisible = false;
DataGridTextBoxColumn col = new DataGridTextBoxColumn();
col.HeaderText = "Name";
col.MappingName = "ListBy";
col.Width = NameColumnWidth;
tableStyle.GridColumnStyles.Add(col);
grdPerson.TableStyles.Add(tableStyle);
currencyManager = (CurrencyManager) grdPerson.BindingContext[dataView];
currencyManager.PositionChanged += new System.EventHandler(PositionChanged);
}
// textFind is TextBox where user types in the filter.
// User types "A", grid filters to people named "A*".
// ApplyTextFilter() is called when the TextChanged event is fired.
void ApplyTextFilter()
{
string findText;
string filter;
findText = txtFind.Text;
if (findText == "")
filter = "";
else
filter = "ListBy Like '" + findText + "*'";
dataView.RowFilter = filter;
// Highlight first record in grid
if (dataView.Count > 0)
grdPerson.Select(0);
}
//
// Here is an excerpt of code from my MainForm.
// nvgPerson is an instance of my Navigator user control.
// db is an instance of a class that handles connected to my database.
// nvgPerson is bound to a DataView based on a table from db.DataSet.
// Other controls are bound directly to fields in a table in db.DataSet.
//
DataView dataView = new DataView(db.DataSet.Tables["person"]);
nvgPerson.SetDataBinding(dataView);
txtFirst.DataBindings.Add("Text", db.DataSet, "person.FirstName");
txtMiddle.DataBindings.Add("Text", db.DataSet, "person.MiddleName");
txtLast.DataBindings.Add("Text", db.DataSet, "person.LastName");
cbxSuffix.DataBindings.Add("Text", db.DataSet, "person.Suffix");
chkSpouse.DataBindings.Add("Checked", db.DataSet, "person.HasSpouse");
//
// etc
//
My code (without indents) from my Navigator user control, version 2
----------------------------------------------------------------------
// In this version, the DataGrid works as a record selector,
// but I can't get it to filter.
ViewManager viewManager;
public void SetDataBinding(DataViewManager viewManager, string table)
{
const int NameColumnWidth = 130;
grdPerson.DataSource = viewManager;
grdPerson.DataMember = table;
this.viewManager = viewManager;
DataGridTableStyle tableStyle = new DataGridTableStyle();
tableStyle.MappingName = table;
tableStyle.ReadOnly = true;
tableStyle.RowHeadersVisible = false;
DataGridTextBoxColumn col = new DataGridTextBoxColumn();
col.HeaderText = "Name";
col.MappingName = "ListBy";
col.Width = NameColumnWidth;
tableStyle.GridColumnStyles.Add(col);
grdPerson.TableStyles.Add(tableStyle);
currencyManager = (CurrencyManager) grdPerson.BindingContext[viewManager,
table];
}
void ApplyTextFilter()
{
string findText;
string filter;
findText = txtFind.Text;
if (findText == "")
filter = "";
else
filter = "ListBy Like '" + findText + "*'";
viewManager.DataViewSettings["person"].RowFilter = filter;
}
//
// Here is an excerpt of code from my MainForm.
// nvgPerson is an instance of my Navigator user control.
// db is an instance of a class that handles connected to my database.
//
DataViewManager viewManager = new DataViewManager();
viewManager.DataSet = db.DataSet;
viewManager.DataViewSettings["person"].Sort = "ListBy ASC";
nvgPerson.SetDataBinding(viewManager, "person");
txtFirst.DataBindings.Add("Text", viewManager, "person.FirstName");
txtMiddle.DataBindings.Add("Text", viewManager, "person.MiddleName");
txtLast.DataBindings.Add("Text", viewManager, "person.LastName");
cbxSuffix.DataBindings.Add("Text", viewManager, "person.Suffix");
chkSpouse.DataBindings.Add("Checked", viewManager, "person.HasSpouse");
//
// etc
//
-----------------------------------
Thanks!
Patrick