I have a SDK:DATAGRID with 20 columns or so, when it opens up it only shows four fields/columns. Which is what I want and how I designed it
Basically I'm grabbing information based on the user click - EXAMPLE:
OWNERNAME.Text = ((TextBlock)EPICGrid.Columns[1].GetCellContent(EPICGrid.SelectedItem)).Text;
and/or
OWNERNAME2.Text = ((TextBlock)EPICGrid.Columns[16].GetCellContent(EPICGrid.SelectedItem)).Text;
What I'm running into it doesn't grab the information in the cell unless if I scroll and show the column so I can only grab the first 4 columns of data because they show when the grid becomes visible.
I can't grab data from columns 5 -20 unless I scoll over and make those columns visible. They don't have to be visible during the click...it just seems like the data doesn't really load until I view the column.
I guess I should say the first record/row loads all the data/cells/columns and I can grab any data from the first record but the problem happens with records 2 - *.
Just to clarify - my issue is not a visibility of my columns or rows. My issue is the SDK DataGrid seems like it is loading the data on demand. So if the column is not in view at one point or another the information in the cell is not available.
I don't want to show all columns and I don't want to give the user the ability to see all columns so I want to disable the scroll bars but when a user clicks on a certain row I need to grab information in certain cells and since the column is not load yet the information is not there.
How do I turn the feature load on demand off?
I did a search and found out that someone had a similar problem with rows loading and the suggestion was setting the VirtualizingStackPanel.VirtualizationMode = Standard
It almost like the problem is stemmed from VirtualizingStackPanel.VirtualizationMode but I set this property to standard and recycle and no luck.
Here's definition:
By default, a VirtualizingStackPanel creates an item container for
each visible item and discards it when it is no longer needed (such as
when the item is scrolled out of view). When an ItemsControl contains
a lot of items, the process of creating and discarding item containers
can negatively affect performance. When
VirtualizingStackPanel.VirtualizationMode is set to Recycling, the
VirtualizingStackPanel reuses item containers instead of creating a
new one each time.
On initial load, if the cell is not visible I can not grab the cells
content (unless it is the first record/row). Once and after the cell /
column is visible then the information is available.
I think you are expected to deal with the data that the row is bound to directly and not pull the data out of the controls. This makes sense since it is two way data binding so the data is updated as you are changing it (assuming it implements the INotifyPropertyChanged Interface).
An example would be where a datagrid is bound to a collection of type MyEntity.
private void DataGrid1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (this.DataGrid1.SelectedItem == null)
return;
MyEntity myEntity = (MyEntity)this.DataGrid1.SelectedItem;
// at this point you have the (updated) data the row is bound to.
MessageBox.Show("You Selected: " + myEntity.name);
...
Another example is where there is a button on each row. The code to process when a button is clicked looks something like:
private void btnProcessEntity_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
MyEntity myEntity = btn.DataContext as MyEntity;
// clicking a button in a row doesn't select the row, so select it.
this.DataGrid1.SelectedItem = myEntity;
MessageBox.Show("Will Process: " + myEntity.name);
...
}
If you are not familiar with some of the technologies that normally are used with Silverlight check out these Video Tutorials. It is VB.Net, but the code is really not the focus - it is focused on a Silverlight application architecture. I would start with "Intro to SL4 and WCF Ria Services" and then view one of the ones on MVVM.
Related
I've got a DataGridView on a form that loads in some data from a DataTable object when something in a previous step is done (this is a Wizard-type application and this is in a TabControl). When moving from the previous step, there is a file that is put into the DataGridView with a few extra columns added. To clarify: populating the table works exactly as it should - there is no issue with the data itself.
My problem here is that when moving from the previous step, the DataGridView doesn't render correctly. It still shows the previous step where the data should be, and only displays the data when I select cells (either individual cells - where it renders that cell (when I mouse over the readonly=false cells or clicking on the readonly=true cells) or selecting the whole table). Screenshots are below:
When the screen is first rendered:
When I've selected all the cells:
I've tried programmatically selecting all cells (using datagridview1.SelectAll()) after I've populated the DataGridView but that doesn't make any difference. I've also tried using the datagridview1.Select() method and setting datagridview1.CurrentCell = datagridview1.Rows[0].Cells[0].
I'm not sure this can be solved with code - is there a way to make sure the cells render properly or is this an issue with my local machine?
If you loaded the data while the container was hidden in an unselected TabPage it's display updates are blocked.
To bring it to live you can code the Selected event:
private void tabControl1_Selected(object sender, TabControlEventArgs e)
{
foreach (Control ctl in tabControl1.SelectedTab.Controls) ctl.Refresh();
}
I'm running into a problem making multiple selections programmatically in a DataGridView (DGV) based on data table values. I have a table with one column "ID", I need to pass these values to another form with a DGV for editing, ID is the first DGV column also, i.e. for every ID in the table, the appropriate DGV row should be selected.
I can loop through the table and DGV fine, but only the last value is selected even though the DGV properties MultiSelect=true ... when I use the form manually, multiple select works fine.
foreach(DataRow dtrow in dt.Rows)
{
string Selection = dtrow["ID"].ToString();
foreach(DataGridViewRow DGVrow in dgview.Rows)
{
if (DGVrow.Cells[0].Value.ToString().Equals(Selection))
{
dgview.CurrentCell = DGVrow.Cells[0];
int cellInx = dgview.CurrentCell.RowIndex;
dgview.Rows[cellInx].Selected = true;
break;
}
}
}
I'm answering my own question because I don't think this is possible on form load. My application has a form that's used to add selections to a project. When the user wants to 'Edit' the project, I need to call this form and make all the previous selections so the user can add/delete.
When using a DataGridView (DGV) with multi-select enabled, at run time, you can 'ctl-click' and select multiple items ... essentially I'm trying to recreate this behavior in code, on form load in 'edit' mode.
After the form is initialized I have a method that loads the DGV from OleDb tables, to test this out I tried putting the following lines after the load method call and as the last lines of the method call:
dgv1.Rows[0].Selected = true;
dgv1.Rows[1].Selected = true;
dgv1.Rows[2].Selected = true;
Obviously, on form load, I was expecting the first 3 rows to be 'selected', but that didn't happen.
However, I remembered a separate issue, I could never get the DGV to load without the first line selected by default ... so I put in a 'refresh' button, that simply calls the 'Load' method again ... the last line of which is: DGV1.Rows[0].Selected = False; With the refresh button the DGV loads without the first line selected.
I was curious if this was a similar situation, so when I added these 3 lines to the end of the load method, nothing happened on form load ... but ... when I hit the 'Refresh' button, the first 3 rows were 'selected'.
I've been researching this for over 3 days and found the following from the DataGridView Project Manager (2006):
https://social.msdn.microsoft.com/Forums/windows/en-US/cf351d44-4a9a-4c80-8d52-4fb349847908/multiple-select-is-not-working-for-datagridview?forum=winformsdatacontrols
Unfortunately there isn’t an easy solution to this as I didn’t look at this scenario and design the grid to handle this well. The main problem stems from the fact that when you mouse down on the grid, the grid sets the current cell property which clears the selection before selecting the next cell/row/column. So, while your line of code selects the row, when you go to select the next row or just move to the next row using the keyboard, the row you selected is cleared. The easiest way to do your scenario is to use custom painting via the RowPrePaint and paint the “selected” rows using the same SelectedBackground color. You can just query the value of the check box cell in the row that you are painting to know if that row is “selected”, but there isn’t any need to set the Selected property to true. The flip side to this is that you’ll have to keep track or enumerate all rows to know all the “selected” row at a given time.
-> mark -> DataGridView Program Manager - 2006
So my plan going forward is to rebuild the DGV to use check boxes, as recommended. I just wanted to put this out there for general information and/or if someone has a better idea. Thanks
I am struggling to figure out the correct control to use for a list of predefined jobs in the included form. I currently have a ListBoxControl in the Predefined Job Name group that lists all of the predefined jobs for a marine service shop (i.e. oil change, tune up, etc...). Then, based on the item (i.e. job name) that is selected in my ListBox, I need to display the items that correspond to that job. For example, if oil change is the selected job I need to show 4 quarts oil, 1 oil filter, labor, etc...and so on.
Currently, when I load the form data I have a DAO that retrieves all of my jobs from the database using LINQ to SQL. Then I iterate over the results and put the job names into the ListBox. The problem that I am having is that there is no tag for ListBox items like there is for ListView items. So each time the user selects another item in the ListBox, I have to perform another LINQ query to get the job from the database again so that I can display its' corresponding items. If I could use a ListView and hide the column header I could set the entire job on the tag so that each time the user selects a new item I would have access to the details without having to make another call to the database. Is there a way that I can hide the column header of a ListView without hiding the entire column?
You can set the HeaderStyle member of the ListView to None.
listView1.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
Checkout the ListView HeaderStyle property. It has the following options:
None
Nonclickable
Clickable
From MSDN:
The HeaderStyle property allows you to specify whether the column headers are visible or, if they are visible, whether they will function as clickable buttons. If the HeaderStyle property is set to ColumnHeaderStyle.None, the column headers are not displayed, although the items and subitems of the ListView control are still arranged in columns
You can also create simple object like ListItem which has two poperties: Text (string) and Tag (object). Then implement ListItem.ToString() and you can use these in the ListBox as well.
You can also check out Better ListView Express component, which is free and allows displaying items in Details view without columns. The advantage over ListBox and ListView is a native look and many extra features.
Easy way is using the ColumnWidthChanging event
private void listViewExtended1_ColumnWidthChanging(object sender, ColumnWidthChangingEventArgs e)
{
if (e.ColumnIndex == 0)
{
e.Cancel = true;
e.NewWidth = listViewExtended1.Columns[e.ColumnIndex].Width;
}
}
I found that if you know for a fact you are not displaying the headers it may be best to set the HeaderStyle property to None, as Rajesh mentions above.
When setting in the .CS when screen initially loads the headers are displayed until screen is fully rendered.
I realize that the DevExpress GridLookUpEdit editor was not designed to work with data that has multi-part keys. However, I am trying to workaround this limitation anyway.
The data for my GridLookUpEdit is Product-Purity with two columns "PRODUCT_ID" and "PURITY_ID". I have this code to set the purity of the underlying grid when the user selects the product-purity row in the GridLookupEdit:
void lookUpEditProductPurities_EditValueChanged(object sender, EventArgs e)
{
// Get the purity from the product selected and update the purity column of the grid.
DevExpress.XtraEditors.GridLookUpEdit editor = (sender as DevExpress.XtraEditors.GridLookUpEdit);
DevExpress.XtraGrid.Views.Grid.GridView view = editor.Properties.View as DevExpress.XtraGrid.Views.Grid.GridView;
object val = view.GetRowCellValue(view.FocusedRowHandle, "PURITY_ID");
if (editor.Parent is GridControl)
{
GridControl ParentGridControl = (editor.Parent as GridControl);
GridView ParentGridView = (ParentGridControl.MainView as GridView);
DataRow CurrentDataRow = ParentGridView.GetDataRow(ParentGridView.FocusedRowHandle);
CurrentDataRow["PRODUCT_PURITY_ID"] = val;
}
}
This works fine when I use it from a master grid, with one small problem. When an existing row refers to a purity that is not the first purity for a product, popping the grid will make it appear as though the first purity is selected. This is not a big deal as far as I am concerned.
However: the big problem I am having is when I use this GridLookUpEdit in a detail row of a master-detail grid. The call: editor.Parent is returning the grid control for the master and ParentGridControl.MainView is returning the GridView for the master.
How do I get at the gridView that the GridLookUpEdit is an editor for - the child gridView??
tia -
Your task (getting a detail view) can be implemented using the approach shown in the What can cause the properties, methods, and events of a detail grid view to fail? article - use the
GridView.GetDetailView method.
Please also review the following article:
Navigating Through Master and Detail Rows
I have a DataGridView bound to a list of custom objects created on the fly. This list is not very large, 5000 items maximum. However, the values of the custom objects change every 50ms and the grid hangs the application while refreshing the values and it ultimately crashes.
My question is: is there a way to "virtualize" the data binding of the DataGridView so that only the rows that are actually seen on the screen are refreshed?
EDIT: I found out why my DataGridView was so slow and it had nothing to do with data binding. So this question is no longer relevant. As a side note, I think the DataGridView already refreshes only the visible rows when a ListChanged event occurs.
A good article on Virtual mode (DataGridView). - http://www.codeproject.com/KB/books/PresentDataDataGridView.aspx#7
Spent quite a while searching this issue and this question kept popping up, so I'll link here the answer which solved my problem: https://stackoverflow.com/a/9348149/674884
I have a DataGridView bound to a BindingSource which is also bound by ComboBoxes and TextBoxes used to edit the data. Every Leave event on the editors had a big lag which was caused by the DataGridView redrawing all it's rows when the data was updated. This happened even when using VirtualMode.
The problem was caused by the AllCells autosize setting of DataGridView columns. Every time a value changed the DataGridView went through all the rows to find the longest string for autosizing the column. After disabling autosizing I realized that even the databound DataGridView draws only the visible rows, so no need to use the VirtualMode.
I think you will want to look into using the DataGridView in virtual mode.
What is stopping you just pulling the visible sub-set of items instead of the full 5000?
I don't know if ListChanged already refreshes only the visible rows.
I can't see any indention in MSDN. I will look into DataGridView implementation later and update.
Anyhow the follow works for me:
int scrollPositionFirst = dataGridView1.FirstDisplayedScrollingRowIndex;
// displayedRowCount -> is our visible rows count
var displayedRowCount = dataGridView1.DisplayedRowCount(false);
// the loop will iterate in the amount of the displayed rows
for (int rowCount = 0; index < displayedRowCount; rowCount++)
{
// scrollPositionFirst is our first visable row
// so scrollPositionFirst is our starting point
var set = (Set)dataGridView1.Rows[scrollPositionFirst].DataBoundItem;
// we update the grid from the first visable(displayed) index
UpdateMainGrid(scrollPositionFirst, set);
// increment index -> this is done because we want to update the next visible row
scrollPositionFirst++;
}