I'm looking for a way to dynamically set a column header in a datagrid(if there's a better option than Datagrid for this, please suggest).
Is a set of columns, and 1 of the columns is, for lack of a better term, a columngroup.
for example, it would look like this
Column1 | Column2 | ColumnGroup | Column 4
and ColumnGroup would be a number of columns, determined by the count of data from a stored procedure call.
For example, it will represent the number of region tabs at http://www.thehealthline.ca/ or http://www.eriestclairhealthline.ca/. As you can see, these sites are similar, but have different number of region tabs. I have to generate a table that shows specific data, one of which is related to the region tabs on the site. of which can be any number of region tabs
I realize I've rambled, I hope my problem is understandable. Would love some help from anyone that has an idea of how to do this
also, is there a way to format the columngroup like so?
|MAIN HEADER NAME|
|1|2|3|4|5|6|
You can get your ColumnGroups into a list from the stored procedure and then loop them adding them to data grid like this:
for (int i = 0; i < columnGroupList.Count; i++)
{
if (i == 0)
{
dataGrid.Columns[i].Header = 'Main Header | ' + columnGroupList[i];
}
else
{
dataGrid.Columns[i].Header = columnGroupList[i];
}
}
And you can add your other headers one at a time:
dataGrid.Columns[0].Header = ColumnHeader1;
dataGrid.Columns[1].Header = ColumnHeader2;
.
.
.
Related
I need to check existing datarows(for all columns) for possible duplicates in a datatable before adding a new row. Currently using the approach of adding a new datarow(using itemarray) to the table dt1 and comparing the row count of the existing table(dt1) and new table(dt1.dataview.totable(true)). However this does not seem to be working when the rows contain empty/null values
| Col1 | Col2 |
|------|------|
|Abc | |
| |Xyz |
When i try to add a new datarow - (Abc, ), it gets interpreted as a distinct row. Is there a way to handle such empty/null values using dataview.totable(), or linq approach to check if a row already exists(values of all columns need to be checked), or any other easier way? *the datatable columns get changed dynamically, so can't rely on column names
Gee, either always put in dbnull for a "", or always put in "" for dbnull.
If you don't adopt a set of HARD rules in your data, then coding this out will forevermore be a real pain. Computers and code HAS to have solid rules, and if you designs are well, sort of blank, but sort of null - the whole process becomes painful. This "long time" rule (be 100% defined in your rules) applies to all code - not just this example.
I think for this case? I would just "code right" though this problem if we going to ignore the above. (my choice would be always null - and use a data view against the table to filter and check in one operation.
However, due to the flip flop between "" and nulls?
Then just brute force code this out.
This works:
My table from SQL server:
SELECT FirstName, LastName, HotelName from tblHotels
Above is shoved into a data table - can have nulls.
So, now our code is thus this:
object[] MySearch = new[] { txtFirst.Text, txtLast.Text, txtHotel.Text };
bool bolFound = false;
foreach (var MyRow in MyTable.Rows)
{
if (FindRow(MySearch, MyRow) == true)
{
bolFound = true;
break;
}
}
Response.Write("<h2>Results of search = " + bolFound.ToString() + "</h2>");
}
public bool FindRow(object[] MySearch, DataRow OneRow)
{
object[] ar2;
ar2 = OneRow.ItemArray;
for (int i = 0; i <= Information.UBound(MySearch); i++)
{
if (Information.IsDBNull(ar2[i]))
{
if (MySearch[i] != "")
return false;
}
else if (MySearch[i] != ar2[i])
return false;
}
return true;
}
So, you just loop the rows - and your test converts any db null in the datatable to "". You ASSUME that your search array will ALWAYS use "" and not a dbnull in that array.
Above is less then pretty, but it not a huge amount of code.
I use C#[2013] winform. I drag and drop a datagridview and design it in two cols then I select value from database to it. I now want to merge two headers into one only. The headers already displayed by designing in properties.
I want to merge the columns.
Col1 | Col2
001 | John
I want to merge into one col as
Title
001 | John
How to merge it?
What type of datasource are you binding to... You might just be better to add a new column to a datatable, or property to a class/structure that is a combined value of the two in question. Then just display that one.
If editing is done to any individual field, then update the JOINED column/property as needed.
In the class that you are using as the source for you DataGridView put a new property:
public string Title { get { return this.Col1 + " | " + this.Col2; }}
then delete those two columns and add one column for Title
Assuming you're talking about a DataGridView, there doesn't appear to be an easy built in-solution for this. Perhaps you could simply copy the data from one column to the other and split them with some sort of delimiter (perhaps a comma).
Modify then run following code after you fill your grid with data:
string data = string.Empty;
int indexCol0 = 0;
int indexCol1 = 1;
foreach (DataGridViewRow row in dataGridView1.Rows)
row.Cells[indexCol0].Value = row.Cells[indexCol0].Value + ", " + row.Cells[indexCol1].Value;
dataGridView1.Columns.RemoveAt(indexCol1);
I have a DataGridView containing some columns - some added automatically and some added when a user performs a certain action. Some of the auto-generated columns are not visible, and the visible columns are frozen and read-only. From the user-added columns that are visible, a user can re-order these, and I use the order of these columns for something else later in my code.
The auto-generated columns are of the custom type DataGridViewUnincludedMetadataColumn and the user-generated columns are normal DataGridViewColumns.
The problem:
I am trying to get a DataGridViewColumn[] (called orderedColumnList) which is just the user-generated, visible columns.
I use this code to count the number of auto-generated, visible columns:
int unincludedVisibleColumnCount = 0;
foreach (var unincludedCol in dataGridView_Metadata.Columns.OfType<DataGridViewUnincludedMetadataColumn>())
{
if (unincludedCol.Visible)
{
unincludedVisibleColumnCount++;
}
}
I use this code to get my orderedColumnList:
foreach (DataGridViewColumn col in dataGridView_Metadata.Columns)
{
if (col.GetType() != typeof(DataGridViewUnincludedMetadataColumn))
{
//if the column is going to be visible
//add the column to the orderedcolumnlist
orderedColumnList[col.DisplayIndex - unincludedVisibleColumnCount] = col;
}
}
The problem is that the DisplayIndex doesn't seem to match up with the actual index of where each column is being displayed.
In my tests I'm getting this:
Index | DisplayIndex | Where the column actually is in the display
0 | 0 | 0
1 | 1 | 1
2 | 4 | n/a - Visible == false
3 | 6* | 5*
4 | 3 | 3
5 | 2 | 2
6 | 5* | 4*
Initially I thought it was just the last column that was off but then I tested by adding another user-generated column and it made the last two columns off by one, so I'm confused as to what the pattern here might be.
Why are the starred values different, and how can I check for this in my code?
I have now figured this out thanks to #stuartd's comment, code is below. This uses the GetFirstColumn() and GetNextColumn() methods on the DataGridViewColumnCollection object with DataGridViewElementStates.Visible.
List<DataGridViewColumn> orderedColumnList = new List<DataGridViewColumn>();
DataGridViewColumn firstCol = dataGridView_Metadata.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
DataGridViewColumn nextCol = dataGridView_Metadata.Columns.GetNextColumn(firstCol, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
while (nextCol != null)
{
if (nextCol.GetType() != typeof(DataGridViewUnincludedMetadataColumn))
{
orderedColumnList.Add(nextCol);
}
nextCol = dataGridView_Metadata.Columns.GetNextColumn(nextCol, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
}
I am working on populating a grid using templates, where I do not know the number of rows and columns, these will be generated via a WCF service in a class that looks something like this:
class GridPoint:
{
string Rowheader;
float cellvalue;
}
class ColumnData: List<GridPoint>
{
}
So the datagrid code would be something like this:
MyGrid: DataGrid
{
InitializeComponent();
private void DataGrid_AutoGeneratingColumn(objectsender,DataGridAutoGeneratingColumnEventArgs e)
{
var col = new DataGridTextColumn {Binding = new Binding(e.PropertyName), Header = e.PropertyName};
e.Column = col;
}
}
I found a way to auto generate columns with the data template in this post. However, they have no mention of adding the row header for each point. I would appreciate your help in adding a row header to the mix into the column style.
The end product should look something like this:
Column1 Column2
Row1 123 123
Row2 811 811
Row3 123 123
A hack I can think of is just generating an extra column with a different style similar to the column header style and adding my row points in it.
If you are talking about populating a DataGrid in WPF, unless you set
AutoGenerateColumns="False"
in your XAML your grid will have it's columns automatically built from the public properties.
The number of rows is not important unless you for some reason need to set a hard limit on the maximum number.
I have a situation where I want to make a generic codebehind function to show a message row that spans the whole table. I have previously passed the Table object and the number of columns so that it could set the column span, but this is somewhat error prone as we sometimes add new columns and I have to update the column count numbers for the messages.
There doesn't seem to be any column count in the Table object and neither any way to get the TableHeaderRow that has been added in the aspx file. I'd like to avoid having to add id's to all the TableHeaderRow's as well.
Try this, should work (assuming the TableHeaderRow is the first child of the Table):
int j = 0;
foreach (Control current in tableId.Controls[0].Controls)
{
if (current.ToString() == "System.Web.UI.WebControls.TableHeaderCell")
{
j++;
}
}