ASP.NET Gridview truncate BoundField from code behind - asp.net

I am adding a dynamic column to an ASP.NET grid view.
Code to add the dynamic column:
List<DataControlField> columns; // this contains all gridview columns.
BoundField boundField = new BoundField();
boundField.DataField = long_text_column.SortExpression;
boundField.SortExpression = long_text_column.SortExpression;
columns.Insert(0, boundField);
How can I trim / truncate long_text_column to show only first 15 characters on the UI.
NOTE: I do not want to trim at the database level for other reasons.

I would add an extra property to the class with only a get that returns long_text_column with a max length of 15.
public class DataControlField
{
public string long_text_column { get; set; }
public string long_text_column_max15
{
get
{
if (!string.IsNullOrEmpty(long_text_column) && long_text_column.Length > 15)
return long_text_column.Substring(0, 15);
else
return long_text_column;
}
}
}

Related

Databinding from text file to gridview

I'm attempting to read a text file, place it into an array separating each entry by \t or \n, then displaying it to a gridview. Here is my code:
private void importExcel()
{
//read in textfile and place it into a datatable
StreamReader reader = new StreamReader("testfile.txt");
string[] words = reader.ReadToEnd().Split('\t','\n');
ReleasePortal.DataSource = words;
ReleasePortal.DataBind();
}
<asp:GridView ID="ReleasePortal" runat="server">
</asp:GridView>`
What ends up happening is all the data is placed into a single column even if I create extra columns in gridview. I understand how to get it to work if I were to use a database using DataTextField and DataValueField. Since I am retrieving this data from a textfile(converted from excel) it has no field identifiers and I dont understand how to put the data into the correct format in gridview. I can do this directly from the excel file but I need to do this from a text file though. Any ideas?
the words are one-dimensional array, you want to create a table. You should define a type representing the line (use correct descriptive names, of course):
public class Foo
{
public string Col0 { get; set; }
public string Col1 { get; set; }
public string Col2 { get; set; }
}
Then, you should first split the result per lines and then by columns, like this:
string[] lines = reader.ReadToEnd().Split('\n');
List<Foo> data = new List<Foo>();
foreach (var line in lines)
{
string[] words = line.Split('\n');
var gridLine = new Foo { Col0 = words[0], Col1 = words[1], Col2 = words[2] };
data.Add(gridLine);
}
ReleasePortal.DataSource = data;
ReleasePortal.DataBind();

ASP.Net Custom Control

I am developing a custom control that needs to display a dropdownlist as a composite control.
The drop down list gets populated from a Rest web service. The problem I am facing is that the dropdownlist only has DataTextField and DataValueField but I need a way of storing more values in the control i.e. I have a couple of other properties I need to access for the selected item.
What is the best way of going about this?
Here is the code I have so far:
[ValidationProperty("SelectedValue")]
public class SelectSurveyControl : Panel
{
private DropDownList ddlSurveys;
public string SelectedSurveyId
{
get
{
return SelectedValue;
}
}
public string SelectedSurveyJavascriptEmbedCode
{
get
{
return this.ddlSurveys.SelectedItem.Attributes[""];
}
}
public string SelectedValue
{
get
{
return ddlSurveys.SelectedValue;
}
set
{
if (ddlSurveys == null)
{
ddlSurveys = new DropDownList();
}
ddlSurveys.SelectedValue = value;
}
}
protected override void OnLoad(EventArgs e)
{
base.OnInit(e);
if (ddlSurveys == null)
{
ddlSurveys = new DropDownList();
}
IList<Survey> surveys = GetSurveys();
this.ddlSurveys.DataSource = surveys;
this.ddlSurveys.DataTextField = "title";
this.ddlSurveys.DataValueField = "id";
this.ddlSurveys.DataBind();
ddlSurveys.SelectedValue = this.SelectedValue;
ddlSurveys.CssClass = "umbEditorTextFieldMultiple charlimit";
ddlSurveys.Attributes.Add("SurveyId", SelectedSurveyId);
ddlSurveys.Attributes.Add("JavascriptEmbedingCode", SelectedSurveyId);
this.Controls.Add(ddlSurveys);
}
public IList<Survey> GetSurveys()
{
...
}
}
Try using a string join/split to store and retrieve the various values, then you don't have to customize your dropdown list very much.
For Example:
Text: Some Title
Value: 1|testing test|2/12/2010
This will let you store as many values as you want, so long as you choose an appropriate character to join and split on. I usually use the bar, as in my example above.
Side Note: I was looking at your selected value set handler and it needs some tweaking. You shouldn't check for a null drop down list, instead you should call EnsureChildControls() before each get and set instead. Make sure you override the CreateChildControls() method and create your controls there.
You could use a hidden field and iterate thru a copy of the returned Surveys like this:
foreach(Survey s in Surveys){
string val = s.id + ":" + s.<property1> + ":" + s.<property2>;
hiddenField.Value += val +",";
}
When you need to read from the hidden field, you use String.Split to separate the values into arrays using ',' as the separator and in each array, you split again using ':'.
In the first split Array1[0] who be the survey id and Array1[n!=0] would be the properties of the Survey with the id = Array1[0]. Array[n!=0] would then be split into Array2.
I would suggest handling empty property values with an empty string or something or else you might end up with unequal lengths especially if you specify StringSplitOptions.RemoveEmptyEntries.
Agricfowl

Have to select gridview row twice for dropdown to select correctly

I'm using the code below to extract data from a gridview and populate it into textboxes for the days and two drop downs for Project and Category.
For some rows in the gridview everything but the category ddl populates correctly. If I click the row a second time the category ddl displays the correct category.
Can anyone tell me why I have to click twice for some rows? And how do I fix this?
Thank you
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
//// Get the currently selected row using the SelectedRow property.
GridViewRow row = GridView1.SelectedRow;
txtSunday.Text = (row.Cells[6].Controls[0] as DataBoundLiteralControl).Text.Trim();
txtMonday.Text = (row.Cells[7].Controls[0] as DataBoundLiteralControl).Text.Trim();
txtTuesday.Text = (row.Cells[8].Controls[0] as DataBoundLiteralControl).Text.Trim();
txtWednesday.Text = (row.Cells[9].Controls[0] as DataBoundLiteralControl).Text.Trim();
txtThursday.Text = (row.Cells[10].Controls[0] as DataBoundLiteralControl).Text.Trim();
txtFriday.Text = (row.Cells[11].Controls[0] as DataBoundLiteralControl).Text.Trim();
txtSaturday.Text = (row.Cells[12].Controls[0] as DataBoundLiteralControl).Text.Trim();
// Set ProjectList ddl to Project in selected row
if (ProjectList.Items.FindByText(row.Cells[2].Text.Trim()) != null)
{
ProjectList.ClearSelection();
ProjectList.Items.FindByText(row.Cells[2].Text.Trim()).Selected = true;
}
/// This is the ddl that doesn't always populate correctly unless you click the
/// gridview row selector twice
// Set CategoryList ddl to Category in selected row
if (CategoryList.Items.FindByText(row.Cells[4].Text.Trim()) != null)
{
CategoryList.ClearSelection();
CategoryList.Items.FindByText(row.Cells[4].Text.Trim()).Selected = true;
}
}
I'm not sure why it's taking two clicks to get your drop down list to select correctly, but it might have to do with postback event ordering/ViewState issues. One thing you may want to consider is using the data you're binding the grid to rather than the text of the controls in the grid. IOW, assuming you're binding to an collection of objects like this:
public class ProjectSchedule
{
public string Project {get;set;}
public int CategoryId {get;set;}
public string Category {get;set;}
public string Sunday {get;set;}
public string Monday {get;set;}
public string Tuesday {get;set;}
public string Wednesday {get;set;}
public string Thursday {get;set;}
public string Friday {get;set;}
public string Saturday {get;set;}
}
Then, in the SelectedIndexChanged event handler, get your data like this:
GridViewRow row = GridView1.SelectedRow;
ProjectSchedule ps = row.DataItem as ProjectSchedule;
if (ps != null)
{
txtSunday.Text = ps.Sunday;
// the rest of the days...
ListItem categoryItem = CategoryList.Items.FindByText(ps.Category);
if (categoryItem != null)
{
CategoryList.ClearSelection();
categoryItem.Selected = true;
}
// same with ProjectList
}
Assuming your controls are going to land in the same column every time limits maintainability. For instance, say the requirements change to say the columns with the days are before the Project column. That's a lot of indices to change.
It would be even better if you have your categories and whatnot indexed by something (e.g., the CategoryId property I smuggled into the ProjectSchedule object above), then you could look up the item by value instead of by text, relieving another point of failure.
I think I figured this out. I needed to rebind the category ddl after setting the project
// Set ProjectList ddl to Project in selected row
if (ProjectList.Items.FindByText(row.Cells[2].Text.Trim()) != null)
{
ProjectList.ClearSelection();
ProjectList.Items.FindByText(row.Cells[2].Text.Trim()).Selected = true;
}
// Set CategoryList ddl to Category in selected row
// I added this line and it seems to work now
CategoryList.DataBind();
if (CategoryList.Items.FindByText(row.Cells[4].Text.Trim()) != null)
{
CategoryList.ClearSelection();
CategoryList.Items.FindByText(row.Cells[4].Text.Trim()).Selected = true;
}

Binding sclar values in C# grid controls

Recently I have been using both the ASP.Net GridView Control and the WinForms DataGridView to display data dynamically. In both cases I have been using various generic Lists as the datasource (List<T>). When this list in as a collection of types with properties defined, these controls have no problem binding to a named property, and in the case of the DataGridView will display the properties as headers with the values for each property as the rows.
However when I have a collection of strings or ints for example, these controls have trouble binding to the values contained in the lists. I'm creating my ASP GridView control dynamically so its not defined in the page untill it is needed so I don't think a binding expression will work here, although I'm new to binding expressions so I could be wrong:
GridView grid = new GridView();
grid.AutoGenerateColumns = false;
grid.CssClass = "summaryTable";
grid.Columns.Add(new TemplateField { HeaderText = "Error No.", ItemTemplate = new DataGridAutoNumber(grid) });
grid.Columns.Add(new BoundField { HeaderText = "Error Description", DataField="Value" });
grid.DataSource = validator.ValidationErrors;
grid.DataBind();
In the above example validator.ValidationErrors is a list of strings. In order to get the GridView to bind the string values I had to wrap them in a type I created:
public class ValueItem<T>
{
T value;
public ValueItem(T valueIn) { value = valueIn; }
public T Value { get { return value; } }
}
This type works for both GridView and DataGridView and allows me to create a List<ValueItem<T>>() of any value type so I can bind it to a Grid type control.
Now am I missing something here or do these controls just not work well with collections of value types?
Apologies for the long question!
P.S. As a side note if anyone knows how to create an autonumber column in a GridView in the code not the script, please let me know. My solution was this:
public class DataGridAutoNumber : ITemplate
{
GridView grid;
public DataGridAutoNumber(GridView gridIn) { grid = gridIn; }
#region ITemplate Members
public void InstantiateIn(Control container)
{
container.Controls.Add(new Label{ Text=(grid.Rows.Count+1).ToString()});
}
#endregion
}
you already know how to add Label to GridView.
Here is one logic to add auto numbering i.e. row number to grid
Untested code
protected void gv_DataBound(object sender, EventArgs e)
{
int pageIndex = gv.PageIndex;
int pagesize = 20;
int count = pagesize * pageIndex;
foreach (GridViewRow row in gv.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
count ++;
Label lbl = row.FindControl("lblAutoNumber") as Label;
lbl.Text = count.ToString();
}
}
}

Dynamic change of an editor type for ASPxGridView

I have an ASPxGridView from DevExpress fed with data from ObjectDataSource. My data row objects expose properties such ParameterName, ParameterType and ParameterValue.
//Properties, constructor and private fields code omitted for clarity
public class InputParameterDescription
{
public string ParameterName;
public Type ParameterType;
public int ParameterPrecision;
public string ParameterDescription;
}
ParameterValue is always an object of type indicated by ParameterType property. In fact, I use few types – Int32, Double, String or Boolean. When I display values in a grid and user clicks “Edit” a ParameterValue is always edited with TextBox. Is it possible to change editor for this column according to ParameterType? I want my users to use SpinEdit for integers, checkbox for Boolean, etc.
In fact, this is the way people have been working with DevExpress Delphi grids - TdxGrid and TcxGrid (OnGetProperties event). I have asked this question in DevExpress forum, but haven’t got any answer :(
You could create a template on that column that would do the switch for you. Something like:
public class SwitchTemplate : ITemplate
{
public void Instantiate(Control container)
{
GridViewDataItemTemplateContainer cnt = (GridViewDataItemTemplateContainer) container;
switch( GetStringParameterTypeFromDataItem(cnt.DataItem) )
{
case "Int32":
container.Controls.Add( new ASPxSpinEdit() { ... } );
break;
case "DateTime":
container.Controls.Add( new ASPxDateEdit() { ... } );
break;
case "String":
container.Controls.Add( new ASPxTextBox() { ... } );
break;
...
}
}
}
Then you just need to specify this template as the EditItemTemplate of the column:
myGrid.Columns["MyColumnName"].EditItemTemplate = new SwitchTemplate()

Resources