I have a datagridview and it's source is a bindingSource. I filter them by Id, name and date.
Also have clear button for clearing filters.
private void b_clear_Click(object sender, EventArgs e)
{
txt_filterNum.Clear();
txt_filterName.Clear();
if (File.Exists(inputpath))
{
//MyLoad();
bindingSource1.Filter = string.Empty;
timeFilter.CustomFormat = " ";
timeFilter.Text = null;
timeFilter.Format = DateTimePickerFormat.Custom;
gridFilter.Update();
gridFilter.Refresh();
}
}
I'm having a really hard time filtering this gridview and clearing the filters.
Here I add my filter too.
bindingSource1.Filter = $"Flight_Date = #{timeFilter.Value:M/dd/yyyy}# AND {gridFilter.Columns[indexRoleName].HeaderText} LIKE '%{txt_filterName.Text}%' AND {gridFilter.Columns[indexRoleNum].HeaderText} LIKE '%{txt_filterNum.Text}%'";
I call it in textboxes_changed and datetimePicker_valuechanged.
I can't filter the values properly, When I try to delete the filtering I have done, I can not get a reset in the datagridview.
Related
I am working with WinForm in this i have 3 RadioButton one ComboBox and have three BindingSource
I want that when I check any of the RadioButtons, the values from the particular DataSources get bound to the ComboBox's ValueMember and DisplayMember.
The program has a SQL query where I want to send value based on the checked radio button.
private void rdbMed_CheckedChanged(object sender, EventArgs e)
{
cmbStock.DataSource = null;
cmbStock.DataSource = this.medicinesBindingSource;
this.cmbStock.DisplayMember = ""; //i want to bind "Med_ID" from medicinesBindingSource
this.cmbStock.ValueMember = ""; //"Med_Name"
}
private void rdbCat_CheckedChanged(object sender, EventArgs e)
{
cmbStock.DataSource = null;
cmbStock.DataSource = this.categoriesBindingSource;
this.cmbStock.DisplayMember = ""; //"category_Name"
this.cmbStock.ValueMember = ""; // category_ID"
}
private void rdbPharm_CheckedChanged(object sender, EventArgs e)
{
cmbStock.DataSource = null;
cmbStock.DataSource = this.pharmaceuticalBindingSource;
this.cmbStock.DisplayMember = "";// "Pharma_Name"
this.cmbStock.ValueMember = "";// "Pharma_ID"
}
Bellow are the parameter of the Query. It will help you to understand what I want to achieve.
if (rdbMed.Checked)
{
con.cmd.Parameters.AddWithValue("#Med_ID", cmbStock.ValueMember);
con.cmd.Parameters.AddWithValue("#category_ID", "");
con.cmd.Parameters.AddWithValue("#Pharma_ID", "");
}
else if (rdbCat.Checked)
{
con.cmd.Parameters.AddWithValue("#Med_ID", "");
con.cmd.Parameters.AddWithValue("#category_ID", cmbStock.ValueMember);
con.cmd.Parameters.AddWithValue("#Pharma_ID", "");
}
else if (rdbPharm.Checked)
{
con.cmd.Parameters.AddWithValue("#Med_ID", "");
con.cmd.Parameters.AddWithValue("#category_ID", "");
con.cmd.Parameters.AddWithValue("#Pharma_ID", cmbStock.ValueMember);
}
Easiest and the least pain way of doing this is resolving it inside SQL command and way to do it is cast your columns with AS VM and AS DM and make your DisplayMember = "DM" and ValueMember = "VM", so if you have sql query like SELECT USERID AS VM, NAME AS DM or SELECT PRODUCTID AS VM, NAME AS DM it will both work.
Problem later is if you do something with code and you may make mistakes trying to get USERID from databinding but it is instead VM. To avoid this you could "double select" values in query like SELECT USERID, NAME, ...., USERID AS VM, NAME AS DM this way you will have VM and DM for your controls but still hold original columns.
i have listview and textbox for search in listview every time user type in textbox i run new query, is there any better way to do that?without running query from database just from itemsources?
private void txtEditSearch_TextChanged(object sender, TextChangedEventArgs e)
{
if (txtEditSearch.Text != string.Empty)
{
var query = GetAllSchoolsAsync(txtEditSearch.Text);
query.Wait();
List<DataClass.Tables.School> data = query.Result;
if (data.Any())
dgv.ItemsSource = data;
}
else
getSchool();
}
i need something like this:
var basedata = dgv.Itemsource;
dgv.ItemSource = basedata.where(x=>x.Name == txtEditSearch.Text).Select(x=>x);
if the listview is populated with data you can filter on that data which acts just like a search, just displays the data you asked for. Here is the link I learnt about this from:
http://www.wpf-tutorial.com/listview-control/listview-filtering/
The best way, I recommend you, to achieve this is creating an initial unfiltered collection and filter from this collection.
Make a private field to store the initial School items:
private List<DataClass.Tables.School> _initialCollection;
Fill it with the unfiltered items in the contructor:
public MyView()
{
var query = GetAllSchoolsAsync();
query.Wait();
_initialCollection = query.Result;
}
In the TextChanged eventhandler you can add the filtering to theItemSource of the ListView:
private void txtEditSearch_TextChanged(object sender, TextChangedEventArgs e)
{
dgv.ItemSource = _initialCollection.Where(x=>x.Name == txtEditSearch.Text).Select(x=>x);
}
So I have a DataGridView which I am using as a “row selector” on a form, and a bunch of controls are bound to the bindingSource.
One of the bound controls is a ComboBox serving as a lookup which enables status choices for the rows, this is populated from a DataTable with data pulled from the DB.
The population of this box is without any issue.
When a given row is selected from the DGV the form controls display data from the given row as they should, however the “statusComboBox” is not quite playing the game.
If in the DGV, I choose a row that has a different status to one previously selected, it works as it should, however, if I choose a row with the same value to a previously selected row, instead of the box showing the DisplayMember it shows the ValueMember.
IT only seems to occur in the above scenario, where the rows selection only instigates a display response from the bound ComboBox providng a previous selection had a different “Status ID”. What have I dont wrong that would cause this behaviour?
So the form load looks like this
private void ProjectsForm_Load(object sender, EventArgs e)
{
InitBindingSource();
//// bind Selector
//ASMod$ this needs to be 'true' unless you explicitly declare columns
ProjectsDataGridView.AutoGenerateColumns = false;
ProjectsDataGridView.DataSource = ProjectsBindingSource;
GetData();
//Set GeneralStatusBox
Helpers.GeneralStatusInitLookup(statusComboBox, ProjectsBindingSource);
}
The ProjectBindingSource is initialised thus:
private void InitBindingSource()
{
ProjectsBindingSource = new BindingSource();
projectsBindingNavigator.BindingSource = ProjectsBindingSource;
ProjectsBindingSource.PositionChanged += new EventHandler(ProjectsBindingSource_PositionChanged);
}
A ProjectsAddDataBindings procedure, and the contained DataBindings.Add for the ComboBox (executed at the end of a GetData routine that additionally populated ProjectsBindingSource):
ProjectsAddDataBindings();
{
…
this.statusComboBox.DataBindings.Add("Text", ProjectsBindingSource, "GSID");
…
}
After the GetData block the GeneralStatusInitLookup populates the Lookup elements, in a helper class simply because it provides functionality to a number of different forms
public static void GeneralStatusInitLookup(System.Windows.Forms.ComboBox comboBox, BindingSource primaryBindingSource)
{
string statusFilter = "";
statusFilter = Helpers.GetStatusGroupFilter(EndeavourForm.FilterId);
if (statusFilter != "")
{
statusFilter = " WHERE " + statusFilter;
}
//// string statusFilter = ""; //// temp
string sql = "";
sql = "SELECT GSID, ShortName FROM GeneralStatus" + statusFilter + " ORDER BY Pos";
GeneralStatusDataTable = Helpers.Db.GetDataTable(sql);
comboBox.DataSource = GeneralStatusDataTable;
comboBox.DisplayMember = "ShortName";
comboBox.ValueMember = "GSID";
comboBox.DataBindings.Add(new Binding("SelectedValue", primaryBindingSource.DataSource, "GSID"));
}
And the DGV initiated row change is handled like this
private void ProjectsBindingSource_PositionChanged(object sender, EventArgs e)
{
try
{
// Update the database with the user's changes.
UpdateProjects();
statusComboBox.SelectedValue = (int)CurrentDataRowView.Row["GSID"];
}
catch (Exception)
{
}
}
private void UpdateProjects()
{
try
{
ProjectsDataAdapter.Update((DataTable)ProjectsBindingSource.DataSource);
DataHelper.CommitProposedChanges(projectsDataSet);
if (this.projectsDataSet.HasChanges() == true)
{
ProjectsBindingSource.EndEdit();
ProjectsDataAdapter.Update();
}
CurrentDataRowView = (DataRowView)ProjectsBindingSource.Current;
}
catch (InvalidOperationException)
{
throw;
}
catch (Exception)
{
throw;
}
}
Anyway I hope I haven't swamped readers with to much code, but frankly I cant see where this is going wrong. So any help would be greatly appreciated.
This was a simple solution in the end. Both the GeneralStatusInitLookup() and the ProjectsAddDataBindings() blocks made use of DataBindings.Add ... For the lookup table this was fine, but with the binding to the main table; the later, I had used "Text" as the propertyName parameter.
Consider the following picture
I get the selected row values in the three textboxes shown in the figure when i click a cell using following code.
void dataGridView1_CellClick_1(object sender, DataGridViewCellEventArgs e) {
TBGRNo.Text = dataGridView1.Rows[e.RowIndex].Cells[0].Value.ToString();
TBSName.Text = dataGridView1.Rows[e.RowIndex].Cells[1].Value.ToString();
TBFName.Text = dataGridView1.Rows[e.RowIndex].Cells[2].Value.ToString();
}
My Question is: how will I do the same thing in DevExpress XtraGrid control??
Here is the way that I've followed,
int[] selRows = ((GridView)gridControl1.MainView).GetSelectedRows();
DataRowView selRow = (DataRowView)(((GridView)gridControl1.MainView).GetRow(selRows[0]));
txtName.Text = selRow["name"].ToString();
Also you can iterate through selected rows using the selRows array. Here the code describes how to get data only from first selected row. You can insert these code lines to click event of the grid.
You can do this in a number of ways. You can use databinding (typical initialized after InitializeComponent();)
textBox1.DataBindings.Add(new Binding("Text", yourBindingSource,
"TableName.ColumnName", true, DataSourceUpdateMode.OnPropertyChanged));
or use a DataLayoutControl (if you are going to use textbox for editing, I really recommend spending some time to learn how to use this component.
or in FocusedRowChanged by assigning from one of these methods:
textBox1.Text = gridView1.GetDataRow(e.FocusedRowHandle)["Name"].ToString();
textBox1.Text = gridView1.GetFocusedDataRow()["Name"].ToString();
textBox1.Text = (gridView1.GetFocusedRow() as DataRowView).Row["Name"].ToString();
textBox1.Text = gridView1.GetFocusedRowCellValue("Name").ToString();
I found the solution as follows:
private void gridView1_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e)
{
TBGRNo.Text = gridView1.GetRowCellValue(gridView1.FocusedRowHandle, "GRNo").ToString();
TBSName.Text = gridView1.GetRowCellValue(gridView1.FocusedRowHandle, "SName").ToString();
TBFName.Text = gridView1.GetRowCellValue(gridView1.FocusedRowHandle, "FName").ToString();
}
Which one of their Grids are you using? XtraGrid or AspXGrid? Here is a piece taken from one of my app using XtraGrid.
private void grdContactsView_RowClick(object sender, DevExpress.XtraGrid.Views.Grid.RowClickEventArgs e)
{
_selectedContact = GetSelectedRow((DevExpress.XtraGrid.Views.Grid.GridView)sender);
}
private Contact GetSelectedRow(DevExpress.XtraGrid.Views.Grid.GridView view)
{
return (Contact)view.GetRow(view.FocusedRowHandle);
}
My Grid have a list of Contact objects bound to it. Every time a row is clicked I load the selected row into _selectedContact. Hope this helps. You will find lots of information on using their controls buy visiting their support and documentation sites.
For VB.Net
CType(GridControl1.MainView, GridView).GetFocusedRow()
For C#
((GridView)gridControl1.MainView).GetFocusedRow();
example bind data by linq so use
Dim selRow As CUSTOMER = CType(GridControl1.MainView, GridView).GetFocusedRow()
All you have to do is use the GetFocusedRowCellValue method of the gridView control and put it into the RowClick event.
For example:
private void gridView1_RowClick(object sender, DevExpress.XtraGrid.Views.Grid.RowClickEventArgs e)
{
if (this.gvCodigoNombres.GetFocusedRowCellValue("EMP_dni") == null)
return;
MessageBox.Show(""+this.gvCodigoNombres.GetFocusedRowCellValue("EMP_dni").ToString());
}
var rowHandle = gridView.FocusedRowHandle;
var obj = gridView.GetRowCellValue(rowHandle, "FieldName");
//For example
int val= Convert.ToInt32(gridView.GetRowCellValue(rowHandle, "FieldName"));
I have two grids that I set up using the winforms DataGridView wizard. One is bound to a trips table which is my transactions table and the other is bound to my expenses table. I know a little bit of linq2sql and I now have my expense table inserting with the fk(TripId).
What I want to do is filter the expenses grid based on the tripId. I am already retrieving the TripId PK of the currently selected trip so that part is done. I am just not sure how I would do the filtering considering I am using linq but used the built wizards to bind the tables.
Any help would be appreciated!
Edit: I have gotten this far with bluefeet's help below. The problem now is when I do my filter it just clears the grid instead of filtering based on pk. Here is the full code
private void tripsBindingSource_PositionChanged(object sender, EventArgs e)
{
if (dgvTripGrid.CurrentRow != null)
{
//get selected row index
int index = this.dgvTripGrid.CurrentRow.Index;
//get pk of selected row using index
string cellValue = dgvTripGrid["pkTrips", index].Value.ToString();
//change pk string to int
int pKey = Int32.Parse(cellValue);
//int tripPrimKey = getPkRowTrips();
this.tripExpenseBindingSource.Filter = String.Format("tripNo = {0}",
pKey.ToString());
}
}
Sounds like you want to fill your second datagridview based on the selection in your first datagridview. This one way to do it:
On the Load or Search of my first datagridview, use the event
DataBindingComplete which then populates the second datagridview
based on the id of the record selected in the first datagridview.
Then if the selection in the first datagridview changes, I use the
event on the BindingSource_PositionChanged to repopulate the second
grid.
Code Sample
// this populates the grid.
private void SearchButton_Click(object sender, EventArgs e)
{
// your code to load your grid goes here
}
private void DataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
var drv = datagridview1bindingSource.Current as DataRowView;
if(drv != null)
// your method to load datagridview2 goes here if the selected row is not null
LoadDataGridView2();
}
private void LoadDataGridView2()
{
//populate datagridview2 using the selected row id from datagridview1
}
// finally when the position is changed on the datagridview1 binding source, then re-populate // the datagridview2
private void datagridview2BindingSource_PositionChanged(object sender, EventArgs e)
{
LoadDataGridView2();
}
this is a basic way to populate a second grid based on the selection in the first.
Edit:
Your comment says that you are filling the datagridview with all expenses, so to filter you will want to use the Filter property on the BindingSource for the datagridview. The Filter property allows you to view a subset of the DataSource.
Example from MSDN:
private void PopulateDataViewAndFilter()
{
DataSet set1 = new DataSet();
// Some xml data to populate the DataSet with.
string musicXml =
"<?xml version='1.0' encoding='UTF-8'?>" +
"<music>" +
"<recording><artist>Coldplay</artist><cd>X&Y</cd></recording>" +
"<recording><artist>Dave Matthews</artist><cd>Under the Table and Dreaming</cd></recording>" +
"<recording><artist>Dave Matthews</artist><cd>Live at Red Rocks</cd></recording>" +
"<recording><artist>Natalie Merchant</artist><cd>Tigerlily</cd></recording>" +
"<recording><artist>U2</artist><cd>How to Dismantle an Atomic Bomb</cd></recording>" +
"</music>";
// Read the xml.
StringReader reader = new StringReader(musicXml);
set1.ReadXml(reader);
// Get a DataView of the table contained in the dataset.
DataTableCollection tables = set1.Tables;
DataView view1 = new DataView(tables[0]);
// Create a DataGridView control and add it to the form.
DataGridView datagridview1 = new DataGridView();
datagridview1.AutoGenerateColumns = true;
this.Controls.Add(datagridview1);
// Create a BindingSource and set its DataSource property to
// the DataView.
BindingSource source1 = new BindingSource();
source1.DataSource = view1;
// Set the data source for the DataGridView.
datagridview1.DataSource = source1;
//The Filter string can include Boolean expressions.
source1.Filter = "artist = 'Dave Matthews' OR cd = 'Tigerlily'";
}
I use this type of Filter to show data based on account. For an account, I have a textbox when the user places the account number and I use the TextChanged Event to apply the filter. Then I have a button that is used to remove the Filter from the binding source.
You can apply the same thing to your expense datagridview using the tripid from your first datagridview.