how to filter a grid based on codtions and than bind the grid using xml - c#

I have one text box and a button and a grid
textbox ID-->Client side---------------->txtFirstName
button Name-->Client side--------------->btnSearch
Grid id-->Client side------------------->gvContactUS
On click of button Search i am trying to search a record which i have entered in textbox whose name is is their in the xml file and will show that in the grid
my xml file is :Contact.xml
<CATALOG>
<CD>
<ID>1</ID>
<HeaderDetailID>1</HeaderDetailID>
<FirstName>Basant</FirstName>
<LastName>Gera</LastName>
<EmployeeID>0012</EmployeeID>
<Department>SD</Department>
<Postion>Programmer</Postion>
<Application>P and L - Joint Cost***BI_AP_KL_COST</Application>
<Filter>Africa_ww_READ</Filter>
<AreaorCountryorStation>India</AreaorCountryorStation>
<NetworkDomain>.Net</NetworkDomain>
<Action>
Modification
</Action>
<NameOfController>Nitin</NameOfController>
</CD>
</CATALOG>
I am trying to filter only 1 record which is their into the grid.
But i am getting the full grid.
Code as follows:
protected void btnSearch_Click(object sender, EventArgs e)
{
string FilepathContact;
string FirstName = txtFirstName.Text;
FilepathContact = Server.MapPath("~/Contact.xml");
DataSet dsdata = new DataSet();
dsdata.ReadXml(FilepathContact);
}
if (dsdata.Tables["CD"].Rows.Count != 0)
{
for (int i = 0; i < dsdata.Tables["CD"].Rows.Count; i++)
{
if (Convert.ToString(dsdata.Tables["CD"].Rows[i]["FirstName"]) == Convert.ToString(FirstName))
{
gvContactUS.DataSource = dsdata;
gvContactUS.DataBind();
}
}
}
}
Now I am getting all the records which is their in my grid.
How do i find the element and search if its their than bind the grid only with that record which is their in data set.
I am using .net Framework 2.0 so LINQ dont work her.

Related

How to bind Access database to DataTable?

I'm new to C# and Visual Studio.
I'm working on a project that is searching through a database of information.
I want to bind a database (Microsoft access file) to my datagridview
but I want it to work with my preexisting code which utilizes a datatable converted into a dataview.
My database has a lot of information and I don't want to put it in manually. I've tried binding the information directly to the datagridview (through datasource in the properties) but then searching doesn't work**. I've looked into sql but im trying to avoid learning 2 languages at the same time.
My projects basic functionality contains: 1 combobox (idCbo) containing the search query's 1 datagridview for displaying the information
this setup is for searching one column only, im going to duplicate the code for the oher columns
The name of the column in the datagridview selects the column(id) for filtering then the combo box(idCbo) searches that column for matching characters in the datagridview and comboBox list.
the combo box contains the values 1-100 for searching the column
public partial class Form1 : Form
{
DataTable dt = new DataTable();
DataView dataView;
public Form1()
{
InitializeComponent();
dt.Columns.Add("id", typeof(int));
for (int i = 0; i < 100; i++)
dt.Rows.Add(i);
dataView = new DataView(dt);
this.dataGridView1.DataSource = dataView;
}
private void idCbo_SelectedIndexChanged(object sender, EventArgs e)
{
string query = idCbo.Text;
dataView.RowFilter = $"convert(id,'System.String') LIKE '%{query}%'";
}
}
**
Binding the database to the datagridview while using this code renders column titles but not the information and the code cannot access the database, columns or the rows System.Data.EvaluateException: 'Cannot find column ...
Big thanks to Johng for assisting me with the code :)
CURRENT WORKING CODE
public Form1()
{
InitializeComponent();
}
public static BindingSource gridBindingSource;
private void idCbo_SelectedIndexChanged(object sender, EventArgs e)
{
string query = idCbo.Text;
gridBindingSource = (BindingSource)dataGridView1.DataSource;
if (gridBindingSource != null)
{
if (query == "All")
{
gridBindingSource.Filter = "";
}
else
{
gridBindingSource.Filter = "convert(id,'System.String') LIKE '%" + query + "%'";
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the '_InfoFinalv_2___CopyDataSet.Info' table. You can move, or remove it, as needed.
infoTableAdapter.Fill(this._InfoFinalv_2___CopyDataSet.Info);
idCbo.Items.Add("All");
for (int i = 1; i < 100; i++)
{
idCbo.Items.Add(i);
}
idCbo.SelectedIndex = -1;
}
private void idReset_Click(object sender, EventArgs e)
{
idCbo.SelectedIndex = -1;
}
If you have set up the grids data source in the designer “correctly” then using the DataView as you want can be simplified by using the existing BindingSource that is usually created when you set up the grid’s data source in the designer.
We can use the existing grid’s BindingSource and then use it’s Filter property as opposed to converting the BindingSource to a DataView to filter. This will allow us to set the filter in the grid WITHOUT having to “change” the grids data source.
Remove all the code you have in the form constructor obviously leaving the InitializeComponent(); and add the code below to the forms Load event. In the load event all we do is set up the combo box with the proper values. I added an “All” option to allow the user to “un-filter” the data in the grid.
private void Form1_Load(object sender, EventArgs e) {
// TODO: This line of code loads data into the 'database1DataSet.EmployeeDT' table. You can move, or remove it, as needed.
employeeDTTableAdapter.Fill(this.database1DataSet.EmployeeDT); // <- created by the designer
idCbo.Items.Add("All");
for (int i = 1; i < 100; i++) {
idCbo.Items.Add(i);
}
idCbo.SelectedIndex = 0;
}
Then in the combo boxes SelectedIndexChanged event... change the code as shown below. Cast the grids DataSource to a BindingSource and then use its Filter property.
private void idCbo_SelectedIndexChanged(object sender, EventArgs e) {
string query = idCbo.Text;
BindingSource GridBS = (BindingSource)dataGridView1.DataSource;
if (GridBS != null) {
if (query == "All") {
GridBS.Filter = "";
}
else {
GridBS.Filter = "EmpID LIKE '%" + query + "%'";
}
}
}
Here's the tip:
On the form load, make an ajax call to the database and fetch only the required data columns. Return data will be in JSON that can be used as data for DataTable.
I used it in an MVC project recently and it works fine. If you would like I can share the detailed code and logic.
Not sharing the code since I'm not sure if you are on .Net MVC.

ASP.NET GridView update Source but not commands

I have a gridview. Its datasource is taken from XML by adding some xmlElemens in a list and than set the list as its data source. Now I am implementing a search feature.
So I am filtering the list in this way:
protected void btnSearch_Click(object sender, EventArgs e)
{
XmlDocument doc = new XmlDocument();
doc.Load(prog); //Percorso file xml
List<string> nomi = new List<string>();
XmlElement root = doc.DocumentElement;
XmlNodeList elemLists = root.GetElementsByTagName("nome");
// this binds the gridview to the title text to display
for (int i = 0; i < elemLists.Count; i++)
{
if(elemLists[i].InnerXml.ToString().ToLower().StartsWith(txtSearchMaster.Text.ToLower()) ||
elemLists[i].InnerXml.ToString().ToLower() == txtSearchMaster.Text.ToLower() ||
elemLists[i].InnerXml.ToString().ToLower().EndsWith(txtSearchMaster.Text.ToLower()) ||
elemLists[i].InnerXml.ToString().ToLower().Contains(txtSearchMaster.Text.ToLower()))
nomi.Add(elemLists[i].InnerXml.ToString());
}
GridView1.DataSource = nomi.OrderBy(q => q).ToList();
GridView1.DataBind();
}
The data is shown correctly but the problem is that when I click the button next the column that is auto generated and get the cell content (that is an element of the list) it return the content of the cell at the same index but of the previous data.
How can I overcome to this?
The problem here is that your "filter" as it were is only applied on the search click. If you had hidden state where a search term was stored, and applied it on every postback, if the state exists, then clicking your grid button would work.
<asp:HiddenField ID="SearchString" runat="server" value="" />
and in your btnSearch_Click
SearchString.Value = txtSearchMaster.Text.ToLower().Trim();
and then add the filter logic in Page_Load
if (IsPostBack) {
// filter on hidden value if not empty.
if (!String.IsNullOrEmpty(SearchString.Value)) {
// filter here
}
}
Just fixed by adding
if (!IsPostBack)
{
...
}
in Page_Load and leaving the filter login into the search button click method.

Binding a TextBox to a particular DataRowView in a BindingSource IList property

In my application I have a table containing data for various regions within an organization with related tables containing statistical data about each region. For simplicity I'll represent them as:
____________ ________________ ________________
|Region | |RegionHasDemo | |DemoCategories|
| |1 *| |* 1| |
|-RegionID |----------|-RegionID |----------|-CatID |
|-City | |-CatID | |-SortOrder |
|-Zip | |-Population | |-Archive |
|-State | |______________| |______________|
|__________|
The DemoCategories table contains the types of demographic. For instance, lets say RegionHasDemo represented age populations for my regions. The CatIDs in DemoCategories would be values like Age20to30, Age20to40 ... etc. so that RegionHasDemo represents age group populations for all the regions.
In my application I want to create a form to add region data along with all of the related data. To do this I've created the two binding sources, one for RegionData and one for RegionHasDemo that contains RegionData as it's DataSource. For various reasons on my form I would like to enter the data for RegionHasDemo by binding individual text boxes to the DataRowViews contained in the List property of the RegionHasDemoBindingSource. Note, I do not want to use a grid view.
Here is the code that I use to bind to the text boxes every time the Current property of the RegionData changes:
Note: the table names are different from my sample, RegionData = UNITS; RegionHasDemo = UnitExp; DemoCategories = CatExp.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.OleDb;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
namespace DBsample
{
public partial class Form1 : Form
{
private DataTable DataSource;
private string relatedTableName;
/// <summary>
/// Holsd the values needed to define my text box rows and
/// relate them to the table containing their human readable
/// names, sort order, and active record status.
/// </summary>
private struct textBoxRow
{
public string Key { get; set; }
public TextBox TBox { get; set; }
public Label NameLabel { get; set; }
public string Name { get; set; }
public int Value { get; set; }
}
textBoxRow[] rows;
public Form1()
{
InitializeComponent();
DataSource = injuryDB.UnitExp;
relatedTableName = "CatExpUnitExp";
}
private void Form1_Load(object sender, EventArgs e)
{
this.uNITSTableAdapter.Fill(this.injuryDB.UNITS);
this.catExpTableAdapter1.Fill(this.injuryDB.CatExp);
this.unitExpTableAdapter1.Fill(this.injuryDB.UnitExp);
// Fill data table
// Associate them in the struct in sorted order
// Get a list of categories
DataTable catTable = DataSource.ParentRelations[relatedTableName].ParentTable;
// Sort them while leaving out the ones we don't want
List<DataRow> tbr = (from r in catTable.AsEnumerable()
where r.Field<bool>("ActiveRecord")
orderby r.Field<int>("SortOrder")
select r).ToList();
// The rows we are going to show
rows = new textBoxRow[tbr.Count];
tableLayoutPanel1.RowStyles.Clear();
int rowIndex = 0;
// Create rows and add them to the form
foreach (DataRow r in tbr)
{
textBoxRow tRow = new textBoxRow();
Label lbl = new Label();
lbl.Text = r.Field<string>("CatName");
TextBox tb = new TextBox();
tRow.Key = r.Field<string>("Category");
tRow.Name = r.Field<string>("CatName");
tRow.TBox = tb;
tRow.NameLabel = lbl;
tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.AutoSize));
tableLayoutPanel1.Controls.Add(tRow.NameLabel, 0, rowIndex);
tableLayoutPanel1.Controls.Add(tRow.TBox, 1, rowIndex);
rows[rowIndex] = tRow;
rowIndex++;
}
// Refresh the bindings in the text boxes when the current item changes
unitCatExpBindingSource.CurrentItemChanged += currentItemChanged;
currentItemChanged(null, null);
}
private void uNITSBindingNavigatorSaveItem_Click(object sender, EventArgs e)
{
bool validated = this.Validate();
if(validated == true)
Debug.WriteLine("Validated data to be saved");
else
Debug.WriteLine("Did not validate data to be saved");
this.uNITSBindingSource.EndEdit();
int recordsUpdated = this.tableAdapterManager.UpdateAll(this.injuryDB);
Debug.WriteLine(string.Format("{0} records were changed", recordsUpdated));
}
private void currentItemChanged(object sender, EventArgs e)
{
if (rows == null) return;
// For some reason I have to pass this into the bindingSource's find method instead of a
// straight string of the column name. It has something to do with the fact that we are
// binding to a data relation instead of a DataTable i think. Wadded through so many forums for this...
PropertyDescriptor pdc = unitCatExpBindingSource.CurrencyManager.GetItemProperties()["Cat"];
// Rebind each text box row
foreach (textBoxRow tBoxRow in rows)
{
tBoxRow.TBox.DataBindings.Clear();
// If the record doesn't exist then that means the population for that group is zero
tBoxRow.TBox.Text = "0";
//tbr.TBox.Leave -= existingRecordTBoxChanged;
//tbr.TBox.Leave -= nonExistingRecordTBoxChanged;
// Get the index of the source I want to bind to using the text
int bindingIndex = unitCatExpBindingSource.Find(pdc, tBoxRow.Key);
//object bs = unitCatExpBindingSource[bindingIndex];
if (bindingIndex >= 0)
{
Binding b = tBoxRow.TBox.DataBindings.Add("Text", unitCatExpBindingSource[bindingIndex], "Jumps", true);
}
else
{
// TODO: Create an event that adds a new to the demo table if number not 0
}
}
}
// TODO: for this to work the delete options of the relationships
// for Units -> category tables need to be set to cascade
private void existingRecordTBoxChanged(object sender, EventArgs e)
{
TextBox tBox = (TextBox)sender;
if (tBox.Text == "" || tBox.Text == "0")
{
//DataRow d = (DataRow)tBox.DataBindings[0].DataSource;
}
}
private void nonExistingRecordTBoxChanged(object sender, EventArgs e)
{
TextBox tBox = (TextBox)sender;
if (!(tBox.Text == "" || tBox.Text == "0"))
{
// TODO: Add record to the database
}
}
}
<code>
My problem is that although when my binding seems to be working okay for viewing, i.e. the textboxes change when I navigate through the units. The changes don't save to the database. The changes I make in the text boxes will persist in the DataSet (when I move away from the record and come back they stay the same) but when I save the dataSet close the form and open it back up again the changes are gone. It's as if the dataSet wasn't notified that those values were changed. Furthermore, if I put the related data in a data grid along side my custom text box list I am able to modify the data from the DataGridView and I am able to save the data. Also, when I change the data in my TextBoxes the new values will show up in the DataGridView but still won't be saved...
I'm wondering is the method that I use to bind the text boxes to the data correct. Meaning, can I bind data in the form of a DataRowView contained inside a Binding source and expect it to behave the same as if I used the binding source directly?
Your help is much appreciated. I hope I've given enough information for you to go on. Keep in mind that this code sample is from a prototype. I understand that that it is not best practice. That said I would appreciate any constructive criticism.
After much trial and error I have found the problem. The issue is that I am binding my text box to a DataRowView object. I'm unsure but I think that a DataRowView is meant to be only specifically used within a GridView or ListView component. In my project I want to bind each DataRowView individually to separate text boxes which causes problems because the DataRowViews seem to share some kind of binding property that makes it so that only one of the text boxes gets bound properly. The solution is to pull the DataRow object from the DataRowView and bind the text boxes to that. If anyone has any input as to the differences between DataRows and DataRowViews in the context of data binding it would be much appreciated.
i have same probs in Combobox i have solved it. my code look like
<sdk:DataGridTemplateColumn Width="150" Header="EstimateIOName">
<sdk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox x:Name="cbo" ItemsSource="{StaticResource IOList}" SelectedValue="{Binding Path=EstimateIOName,Mode=TwoWay}" SelectedValuePath="EstimateIOName" SelectionChanged="cbo_SelectionChanged" DropDownClosed="cbo_DropDownClosed" ></ComboBox>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellEditingTemplate>
</sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn Width="180" Header="Selected EstimatedIOName" IsReadOnly="True">
<sdk ataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBlock x:Name="cbo1" Text="{Binding Path=EstimateIOName,Mode=TwoWay}"></TextBlock>
</DataTemplate>
</sdk:DataGridTemplateColumn>
My Code Behind Look like
LoadOperation<ATDueDate> Load1 = context1.Load<ATDueDate>(context1.GetATDueDatesByEntityQuery("I"));
Load1.Completed += (s, ea) =>
{
this.DataContext = Load1.Entities;
comboBox2.ItemsSource = Load1.Entities.Select(a => a.PackageName.Substring(1,2)).Distinct();
};
Button Click
private void button1_Click(object sender, RoutedEventArgs e)
{
context1.SubmitChanges();
MessageBox.Show("Changes Saved");
}

How to Add Data Contents to Data Grid in the Same Page without any Database Connectivity?

Say, I have a TextBox - When the User enters contents into TextBox and Click on Add the Content Should Populate in the DataGrid Without any db connectivity. The User Can add repeated items in the TextBox and Click on Add, So Every Value gets Popluated in the Grid.
How do I achieve this?
You can try something like this, first you have to Imports the System.Collection.Generic namespace
private List<string> addContent(string content)
{
//create a generic list of string type
List<string> s = new List<string>();
for (int i = 0; i < 10; i++)
{
s.Add(content);
}
return s;
}
protected void btnAdd_Click(object sender, EventArgs e)
{
//Passed the List<> as DataSource and then bind the content in the list<> in the DataGrid
this.DataGrid1.DataSource = this.addContent(this.txtadd.Text);
this.DataGrid1.DataBind();
}
I Hope this works for you

LINQ to XML and DataGridView

Hi I’m trying to use a DataGridView for the first time and with LINQ.
Here’s what I’m trying to do:
I want to use it (although it doesn’t have to the DataGridView ) to read and display the contents of an XML file (this bit is working code below) but I want to have an add row button on the form or in the DataGridView that takes the contents of three textboxes and and populates the contents of three columns of the new row. The new row is to be appended to the existing data.
Next I would like to add a Delete button to delete the currently selected row.
And lastly I want a save button that exports the contents of the DataGridView back to an XML file overwriting/updating the existing XML file.
So I stuck at adding the additional data! but as I don't currently have a clue as to the delete or save either I thought I would ask all in one go!!
So this is the code I have to read the xml file:
XDocument xmlDoc = XDocument.Load(#"queues.xml");
var q = from c in xmlDoc.Root.Descendants("Queue")
select new
{
QueueNumber = c.Element("Number").Value,
QueueName = c.Element("Name").Value,
QueuePCC = c.Element("QueueTag").Value
};
dataGridView1.DataSource = q.ToList();
XML document:
<?xml version="1.0" encoding="utf-8" ?>
<Queues>
<Queue>
<Number>
001
</Number>
<Name>
mytest
</Name>
<QueueTag>
xyz
</QueueTag>
</Queue>
<Queue>
<Number>
002
</Number>
<Name>
Adi2
</Name>
<QueueTag>
ABCD
</QueueTag>
</Queue>
</Queues>
ok I have now changed my code to this:
XDocument xmlDoc = XDocument.Load(#"queues.xml");
var q = from c in xmlDoc.Root.Descendants("Queue")
select new Queue
{
Number = c.Element("Number").Value,
Name = c.Element("Name").Value,
QueueTag= c.Element("QueueTag").Value
};
var queryAsList = new BindingList<Queue>(q.ToList());
bindingSource1.DataSource = queryAsList;
dataGridView1.DataSource = bindingSource1;
This allows me to add and delete rows and data from the dataGridView :)
But I can still find no way to writing the data back to XML either from the dataGridView or from the bindingSource1 :(
Any help please?
the bindingSource1.count changes each time I make a change to the data so I think I'm close!
Perhaps you may try working with the xmlDoc saved in the session (thus preserved with the postbacks)... Add the three elements (from the textboxes) to the XmlDoc... And rebind the gridview to the xmlDoc at each postback.
At the end, you could do xmlDoc.save().
For deleting rows, you could use the GridView event, dataGridView1_RowDeleted, to edit the xmlDoc (to remove the node relative to the selected row).
Something like:
protected void ButtonLoadGridView_Click(object sender, EventArgs e)
{
XDocument xmlDoc = XDocument.Load(#"f:\queues.xml");
var q = from c in xmlDoc.Root.Descendants("Queue")
select new
{
QueueNumber = c.Element("Number").Value,
QueueName = c.Element("Name").Value,
QueuePCC = c.Element("QueueTag").Value
};
dataGridView1.DataSource = q.ToList();
Session.Add("xmlDoc",xmlDoc);
}
public void dataGridView1_RowDeleting(Object sender, GridViewDeleteEventArgs e)
{
// get some node information:
int rowIndex = e.RowIndex;
string someNodeInfo = dataGridView1.Rows[rowIndex].Cells[0].Text;
// then edit xml :
XmlDocument xmlDoc = (XmlDocument) Session["xmlDoc"];
xmlDoc.ChildNodes.Item(rowIndex).RemoveAll();
Session.Add("xmlDoc", xmlDoc);
}
protected void ButtonSave_Click(object sender, EventArgs e)
{
XmlDocument xmlDoc = (XmlDocument)Session["xmlDoc"];
xmlDoc.Save(#"f:\queues2.xml");
}

Categories