Last week I started attempting to use Winforms to automate some reports. I am not enjoying the transition (as simple as it may be to some of you)!
I am currently displaying data from a SQL view that I created using Oracle SQL Developer. I accecssed the data by using the DataGridView Tasks to select the table and display it (it seemed like the most straightforward method).
All of the data displays fine. However, I would now like to access the cells in the table. I want to be able to alter the colours of the cells based upon their values and to pull out some of the data if needs be.
To access the data and highlight the rows I was hoping to do something like this
protected void MyGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
int theValue = Convert.ToInt32(e.Row.Cells[0].Text);
if (theValue>0)
e.Row.Cells[0].BackColor = System.Drawing.Color.Red
}
}
It doesn't work because the event is not firing. I think I am supposed to bind the data to my gridview but I have loaded all of the data through the designer. Is this the problem? I have no idea how to code it myself, I tried before but it threw a wobbly.
Furthermore, when I try to change the SQL query for the database through the designer it does not work. I think I am going to lose my mind at this rate!
You need to use the CellFormatting Event on the DataGridView like so
private void MyGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if ((int)MyGridView.Rows[e.RowIndex].Cells[0].Value > 30)
{
e.CellStyle.BackColor = System.Drawing.Color.Red;
e.CellStyle.ForeColor = System.Drawing.Color.White;
}
}
Related
I have a SqlDataSource bound to a GridView with an SQL that takes about 10 seconds to retreive the data.
Also there is a UserControl called "PageSizeControl" which hooks the selected-event of the GridView's SqlDataSource. In this event, I need the DataTable to prepare some settings of the PageSizeControl.
Currently, I'm doing this with following code:
protected void ds_Selected(object sender, SqlDataSourceStatusEventArgs e)
{
SqlDataSourceView dsv = (sender as SqlDataSourceView);
dsv.Selected -= ds_Selected;
DataTable dt = (dsv.Select(DataSourceSelectArguments.Empty) as DataView).Table;
int iRowCount = dt.Rows.Count;
// some gui-adaption like visibility, text, ...
}
In older versions we used e.AffectedRows. But the value stored in e.AffectedRows is not correct when a Filter is applied to the DataSource. And we have use-cases where we don't only need the row count but the whole DataTable.
The problem is, that the .Select() re-executes the Db-Query and this takes another 10s to finish.
I also tried to turn caching on the SqlDataSource on:
EnableCaching="true" CacheDuration="Infinite"
But this wasn't helpful in two reasons:
1. The OnSelected event is not fired when cached data get accessed
2. If the OnSelected event get's fired (because data wasn't yet cached), the .Select() is still executing uncached and takes 10s.
Does anybody have clues how I can get the data without a time-consumpting re-execution of the query? Best would be in the OnSelected, but I'm open for another suggestions.
I got a workaround running that fits my requirements. I use the event GridView.OnRowDataBound and get the DataItem of the first GridRow, which contains the DataTable.
private DataTable oData = null;
protected void gv_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (oData == null && e.Row.DataItem != null)
{
oData = (e.Row.DataItem as DataRowView).Row.Table;
}
}
This solution works, but it looks quite dirty and it requires a GridView (which in my case is no problem). I would be grateful for a more clean solution.
UPDATE
After a longer research with IlSpy I got to the conclusion that it is not possible to get the data in the OnSelected event. Even not if caching is enabled, since cache is written after OnSelected.
So the easiest way is to turn cache on and call the SqlDataSource.Select(...) function where you need the data.
Another way is to get the data by yourself with SqlDataSource.Select(...) and then bind the table it to the controls. But this has some disadvantages. For example: sorting and paging on GridView doesn't work out of the box when bound to a dataset/datatable.
And yet another way is to extract the data from the control which selected it. See above for an example for GridView.
I would like to highlight my lastly new create row in my Data grid, I have reference this page http://social.technet.microsoft.com/wiki/contents/articles/21202.wpf-programmatically-selecting-and-focusing-a-row-or-cell-in-a-datagrid.aspx to get some idea.
According to the reference link above datagrid first have to visualise . The reason of the last row is not focus and high light, might be cause by this reason.
Following is my code structure
private void CommitRow(object sender, DataGridRowEditEndingEventArgs e )
{
//FIRE WHEN ROW IS DONE EDIT
/*
STORING DATA TO DATABASE
*/
SelectRowByIndex(Datagrid, Datagrid.Items.Count - 1); //I refer from msdn blog
}
I tried to put the code SelectRowByIndex into a button , it will highlight the last row. Therefore I believe the code will only work when the grid is show up on UI.
My question is how to highlight the last row before interface is show up? or is that any other method allow me to focusing and high light the new create row?
You are correct, it cannot be highlighted, because it isn't rendered yet.
But you can use the dispatcher to your advantage there.
private void CommitRow(object sender, DataGridRowEditEndingEventArgs e )
{
//FIRE WHEN ROW IS DONE EDIT
/*
STORING DATA TO DATABASE
*/
Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() =>
{
SelectRowByIndex(Datagrid, Datagrid.Items.Count - 1);
}));
}
This should do the trick. It calls the Dispatcher to do it with a priority thats just after rendering. Visually this should happen instantly.
During development with Devexpress, we've encountered the use of a InstantFeedbackSource. Using the Row_Loaded, we would like to adjust values of certain rows. Yet the CellContent isn't changed.
Testsolution:
GetQueryable-Method of my datasource:
private void linqInstantFeedbackSource1_GetQueryable_1(object sender, GetQueryableEventArgs e)
{
e.QueryableSource = _testObjects.AsQueryable();
gridView2.RefreshData();
gridControl2.RefreshDataSource();
}
My Row-loaded event
private void gridView2_RowLoaded(object sender, DevExpress.XtraGrid.Views.Base.RowEventArgs e)
gridView2.SetRowCellValue(e.RowHandle, gridView2.Columns["RandomGuid4"], "lalalala");
}
Information:
gridView2.Columns["RandomGuid4"] is not null and refers to the correct-column.
e.RowHandle Refers to the correct Linenumber
Goal:
I want to achieve the following behavior:
At runtime i want to fill the gird with records. When adding the rows i want to check the row for certain values. When a certain value occurs then several another cells should be filled with combobox, hyperlinks,...
The advised way by devexpress is the event CustomCellEdit. But that event is highly unreliable. We're experiencing issues (exceptions from within the control). I've submitted several tickets so far but no response. So we're searching an alternative.
Could someone point out what i'm exactly missing/doing wrong here?
Thank you for your time.
Note: I've tried the use of RefreshData in my RowLoaded-Event but it doesn't appear to be working.
I have a datagrid view which shows table data from a database
Environment:
- C# 4.0
- SQL Server 2005
- Visual studio 2010
What i want is: On a row to row basis automatically save changes. So when I edit the first row and then leave the row. It should save the changes to the database.
I've used this code:
In the From1 Load:
dataSet1.TblObject.RowChanged += rowUpdate;
The eventhandler:
private void rowUpdate(object sender, DataRowChangeEventArgs e)
{
DataRow dr = e.Row;
if (dr.RowState == DataRowState.Modified)
{
tblObjectTableAdapter.Update(dr);
}
}
When I've edited a row in the grid, tblObjectTableAdapter.Update(dr); is called the data is stored to the table. Which is good. But the event keeps on triggering as if it's called recursively. So the tblObjectTableAdapter.Update(dr); is causing a dataSet1.TblObject.RowChanged event. But I can't differentiate between the both of them. I'm guessing I'm using the wrong event to store my values but I can't find any event that sounds logical to me. What am I doing wrong?
I've made a dataset xsd:
I've picked the dataset as datasource in this gridview:
Ok, I read your post a couple of times now, while I can't help u directly with your problem. I'll try anyway, What u want is that when i make a change, it doesn't update itself immediatly, but saves the information in a list and when u press a button save the updates?
Then You should make a List of Datarows, and each time a row is changed add that item to the list, this way the updates aren't made directly, but only when u press the button. (This is also way better for performance sake.)
So instead of the code
DataRow dr = e.Row;
if (dr.RowState == DataRowState.Modified)
{
tblObjectTableAdapter.Update(dr);
}
U should make
DataRow dr = e.Row;
if (dr.RowState == DataRowState.Modified)
{
DatarowLst.Add(dr);
}
ButtonSave_Click(object sender, eventargs e)
{
foreach (DataRow d in DatarowLst)
{
tblObjectTableAdapter.Update(d);
}
}
EDIT:
Ok sorry for misunderstanding u. I now understand your problem and looked into the issue.
I found some interesting information on Data adapters and tables. It seems the Adapter does a row to row check in order to obtain information about the changes made.(i.e does it need a update or delete command?) Thereby, My GUESS is that this triggers a update to occur and therefore call your event again, and running the method recursivly.
Info found at the REMARK piece on: This site from msdn
They give a link to this site for more information. Maybe you'll find your answer there.
As to a solution for your problem it seems u can leave your event out and just call the update command. Im NOT sure about this cause I dont have time to check on this and I have little experience on this subject.
Well, hope this helps u a bit further..
I'm trying to implement a C# drag and drop row-reorder with a listview which would then update an SQL database with the current order of the rows. I've come across some snippets of code on the internet (one from this website which implemented a 'var' class) but none seem to be working with my needs. I don't need help updating the database as I have a good idea how I'd do this, but can't seem to get the row reordering to work correctly, any input would be appreciated.
-thanks
m&a
Ensure that AllowDragDrop is set to true.
Implement handlers for at least these 3 events
private void myList_ItemDrag(object sender, ItemDragEventArgs e)
{
DoDragDrop(e.Item, DragDropEffects.Link);
}
private void myList_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Link;
}
private void myList_DragDrop(object sender, DragEventArgs e)
{
// do whatever you need to reorder the list.
}
Getting the index of the row you dropped onto may look something like:
Point cp = myList.PointToClient(new Point(e.X, e.Y));
ListViewItem dragToItem = myList.GetItemAt(cp.X, cp.Y);
int dropIndex = dragToItem.Index;
I know this isn't ListView specific, but I have sample code for implementing row drag and drop out of / into a DataGridView. Some of it is obviously control specific, other code is actually pretty generic (such as deciding when its a drag):
http://adamhouldsworth.blogspot.com/2010/01/datagridview-multiple-row-drag-drop.html
Completely forgot the fact that ListView already allows drag-dropping!
I can also add some theory - when the drop occurs on your control, you will need to hit test on those coordinates (likely a method called HitTest) on the ListView to see what row was hit, this is the basis for where to insert the row being dragged.
Unrelated - is that var class perhaps the new var keyword in C#?