What's wrong with this implementation of the DataList repeater? - datalist

I have the following declarative in an ascx which displays a 4 column list of file names. The file names are xlxs files that can be downloaded so the command event is called when the file name is clicked.
<asp:DataList runat="server" ID="dlHistoricalRates" RepeatColumns="4" >
<HeaderStyle>
</HeaderStyle>
<HeaderTemplate>
<span>Historial Rates</span>
</HeaderTemplate>
<ItemTemplate>
<asp:LinkButton id="historicalRate" ClientIDMode="Static"
runat="server" CommandArgument='<%# Eval("filename") %>'
CommandName="Download" OnCommand="historicalRate_OnCommand" >
<%# Eval("filename") %>
</asp:LinkButton>
</ItemTemplate>
</asp:DataList>
The code-behind command code:
protected void historicalRate_OnCommand(object sender, CommandEventArgs e)
{
if (e.CommandName == "Download")
{
if (e.CommandArgument != null)
{
historicalRate_Download(e.CommandArgument.ToString());
}
}
}
But the CommandArgument is an empty string when it should be the file name. I know the express Eval() is working as it display the file names in the control.
Why, is the filename not being passed as the CommandArgument?

Your CommandArgument looks fine but another way for getting LinkButton's arg from sender object:
protected void historicalRate_OnCommand(object sender, CommandEventArgs e)
{
// get the reference of clicked LinkButton
LinkButton lb = sender as LinkButton;
string cmd = lb.CommandName;
string arg = lb.CommandArgument;
if (cmd == "Download")
{
if (arg != null)
{
historicalRate_Download(arg);
}
}
}

Related

Can't seem to get the from <asp:Literal </asp:Literal> property in Web forms

Could someone please pin point me to what i'm doing wrong?
Basically all i need to is get the text from my property but for some reason it always returns as null.
protected void Page_Load(object sender, EventArgs e)
{
orderId.Text = "4567";
}
protected void UpdateOrder(object sender, EventArgs e)
{
var getOrderId = orderId.Text; //always returns null here
}
front end:
<p>
<asp:Label ID="label8" runat="server" AssociatedControlID="orderId"> Order Id: </asp:Label>
<asp:Literal ID="orderId" runat="server"></asp:Literal>
</p> << the orderId is displayed in the browser
<asp:Button ID="updateBtn" runat="server" Text="Update" OnClick="UpdateOrder"/>
What am i doing wrong?
Have you got a control somewhere else on your page called order?
Your literal is called orderId
You're pulling a value from something called order.
Try:-
protected void UpdateOrder(object sender, EventArgs e)
{
var getOrderId = orderId.Text; //always returns null here
}
The problem was that I had
EnableViewState="false"
at the top of my page. I removed it and boom it works

Repeater's child controls will loss data in the ViewState when set a breakpoint in overrided method OnInit in the authored web control

When I click button "Button1" after the first time, the repeater's child controls will lose data in the viewstate. I added a watch on this.ChildControlsCreated. It is always true. This variable should initially be false.
The test code:
/////////////////////CustomRepeater.cs/////////////////////
public class CustomRepeater : Repeater
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e); **// Sets a breakpoint here**
}
}
/////////////////////TestCustomRepeater.aspx/////////////////////
<table>
<cc1:CustomRepeater id="Control1" runat="server">
<ItemTemplate>
<tr><td><%# DataBinder.Eval(Container.DataItem) %></td></tr>
</ItemTemplate>
</cc1:CustomRepeater>
</table>
<asp:Button id="Button1" runat="server" OnClick="Button1_OnClick"></asp:Button>
/////////////////////TestCustomRepeater.aspx.cs/////////////////////
Page_load()
{
if (!IsPostBack)
{
ArrayList dataSource = new ArrayList();
dataSource.Add("a");
dataSource.Add("b");
this.Control1.DataSource = dataSource;
this.Control1.DataBind();
}
}
protect void Button1_OnClick(object sender, EventArgs e)
{
// Nothing to do, just to trigger a POSTBACK
}
You will need to re-bind the Repeater after your postback. You can do it inside the method Button1_OnClick

How to add required validator to ajax AsyncFileUpload?

How to add client side required validator to asyncfileupload ,to enforce user to select file before submitting the page.
You could also set the text of a the hidden textbox in a server side method using C# or VB, rather than a client side Javascript or JQuery function.
protected void afu_UploadedComplete(object sender, AjaxControlToolkit.AsyncFileUploadEventArgs e)
{
afu.SaveAs(Server.MapPath("Uploads\\") + e.FileName);
txt.Text = e.FileName;
}
I use a RequiredFieldValidator that validates an invisible TextBox. The TextBox is filled with an arbitrary text in the OnClientUploadComplete function.
The only thing you cannot is setting the focus when it is validated.
The example uses jQuery.
<ajaxToolkit:AsyncFileUpload runat="server" ID="afu" ClientIDMode="AutoID" UploaderStyle="Traditional" OnClientUploadComplete="asyncUploadComplete" OnClientUploadStarted="asyncUploadStarted" />
<asp:RequiredFieldValidator runat="server" ID="rfv" ControlToValidate="txt" Text="The file is required!" SetFocusOnError="false" />
<asp:TextBox runat="server" ID="txt" style="display:none" MaxLength="0" />
<script type="text/javascript">
// AsyncFileUpload - OnClientUploadComplete
function asyncUploadComplete(sender, args) {
// Assemble info of uploaded file
var contentType = args.get_contentType();
var info = args.get_length() + " bytes";
if (contentType.length > 0) {
info += " - " + contentType;
}
info += " - " + args.get_fileName();
// Put info in the first input field after the AsyncFileUpload control
var source = $(sender.get_element());
source.nextAll('input').val(info);
// Validate immediately
ValidatorEnable(source.nextAll('span')[0], true);
}
// AsyncFileUpload - OnClientUploadStarted
function asyncUploadStarted(sender, args) {
// Clear the first input field after the AsyncFileUpload control
var source = $(sender.get_element());
source.nextAll('input').val('');
}
</script>

Using Telerik RadComboBox within a repeater

I have a repeater that contains a Telerik RadComboBox:
<asp:Repeater ID="rpt" runat="server">
<ItemTemplate>
<telerik:RadComboBox ID="rcb" runat="server" EnableLoadOnDemand="true"
AllowCustomText="true" ItemRequestTimeout="1000"
NumberOfItems="10" MarkFirstMatch="false">
</telerik:RadComboBox>
</ItemTemplate>
</asp:Repeater>
In the ItemDataBound event of the Repeater, I am wiring up the ItemsRequested event like this:
private void rpt_ItemDataBound(object sender, RepeaterItemEventArgs e) {
RadComboBox rcb = (RadComboBox)e.Item.FindControl("rcb");
rcb.ItemsRequested += rcb_ItemsRequested;
}
private void rcb_ItemsRequested(object o, RadComboBoxItemsRequestedEventArgs e) {
// Database call to load items occurs here.
// As configured, this method is never called.
}
Currently, the server-side rcb_ItemsRequested method is never called. I suspect that wiring the ItemsRequested event in the ItemDataBound is problematic, but the problem may lie elsewhere.
Any ideas on how to use the Telerik RadComboBox within a repeater properly?
Have you tried putting the event handler wiring in the markup rather than adding it dynamically?
Also - you are probably aware, but just in case - ItemsRequested is an event that only fires under certain conditions. To quote the docs:
The ItemsRequested event occurs when the EnabledLoadOnDemand property is True and the user types text into the input field or clicks on the drop-down toggle image when the list is empty. - Reference
Does your scenario match the above?
EDIT:
I've tested some code. The following works (The ItemsRequested Event fires for the all ComboBoxes and adds the three test items to the dropdown on the fly..):
Markup:
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<asp:Repeater ID="rpt" runat="server" OnItemDataBound="rpt_ItemDataBound">
<ItemTemplate>
<br />
<telerik:RadComboBox ID="rcb" runat="server" EnableLoadOnDemand="true" AllowCustomText="true"
ItemRequestTimeout="1000" NumberOfItems="10" MarkFirstMatch="false" />
</ItemTemplate>
</asp:Repeater>
</form>
code behind:
protected void Page_Load(object sender, EventArgs e)
{
List<string> data = new List<string>();
data.Add("Item 1");
data.Add("Item 2");
//add some items to the repeater to force it to bind and repeat..
rpt.DataSource = data;
rpt.DataBind();
}
protected void rpt_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
//wire the event
RadComboBox rcb = (RadComboBox)e.Item.FindControl("rcb");
rcb.ItemsRequested += rcb_ItemsRequested;
}
protected void rcb_ItemsRequested(object sender, RadComboBoxItemsRequestedEventArgs e)
{
//add the items when requested.
(sender as RadComboBox).Items.Add(new RadComboBoxItem("Item1", "1"));
(sender as RadComboBox).Items.Add(new RadComboBoxItem("Item2", "2"));
(sender as RadComboBox).Items.Add(new RadComboBoxItem("Item3", "3"));
}

Conditional Item Templates with RadComboBox

I have a RadComboBox that I am using to display department name and abbreviations. I am using an Item Template with a LinqDataSource to make each item appear as:
DeptAbbr - (DeptName)
Here is the code I am using to do this and it works fine:
<telerik:RadComboBox ID="rcbDepartments" runat="server" AppendDataBoundItems="True"
OnInit="rcbDepartments_Init" DataTextField="DepartmentAbbr" AutoPostBack="True"
DataSourceID="ldsDepartments" DataValueField="DepartmentID" HighlightTemplatedItems="true"
NoWrap="true" Width="250px">
<ItemTemplate>
<div>
<b>
<%# Eval("DepartmentAbbr")%></b><%# Eval("DepartmentName", " - ({0})") %>
</div>
</ItemTemplate>
</telerik:RadComboBox>
My question is this. I want to add an initial item in the list that is for "All Departments" and is the default item. I can do this easily, but the problem I'm having is that because I am not storing an "All Departments" entry in the database, the templating shows a blank space at the beginning of the items list when you pull down the combo box. I'm trying to find out if there is any way to template all but first item in the list?
Note: I have also tried do a conditional in the Eval like this:
<b><%# (Eval("DepartmentAbbr") != null) ? Eval("DepartmentAbbr") : "All Departments" %></b><%# Eval("DepartmentName", " - ({0})") %>
But it only evaluates on the items that are databound and not the initial item which I am sticking in manually. In other words, if I change the above statement to be:
<b><%# (Eval("DepartmentAbbr") == null) ? Eval("DepartmentAbbr") : "All Departments" %></b><%# Eval("DepartmentName", " - ({0})") %>
Then I just get a list with one blank item at the top and the rest reading "All Departments".
My work around for this problem has been to do some funky selection stuff with LINQ server side, but that has forced me to get rid of all templating and html formatting.
You can define the 'All Departments' RadComboBoxItem as a static item in the <Items> collection. Since you have enabled the AppendDataBoundItems property, you don't want to bind to your data source until after the control has already bound the static items; otherwise you'll get the blank space you are seeing when expanding the combo box. Also, use DataBinder.Eval(Container, "Text") to render the DepartmentAbbr field. Since you have set this field as the DataTextField for the control, that value will always render. If not, you'll get the empty space again when the control binds to the static item because it doesn't know what DepartmentAbbr is; it only has a Text field. Here's an example to get you going:
<telerik:RadComboBox ID="RadComboBox1" runat="server"
AppendDataBoundItems="True"
DataTextField="Abbr"
AutoPostBack="True"
DataValueField="DeptID"
HighlightTemplatedItems="true"
NoWrap="true"
Width="250px">
<Items>
<telerik:RadComboBoxItem runat="server" Text="All Departments" />
</Items>
<ItemTemplate>
<div>
<b><%# DataBinder.Eval(Container, "Text")%></b><%# Eval("Name", " - ({0})") %>
</div>
</ItemTemplate>
</telerik:RadComboBox>
public partial class _Default : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
RadComboBox1.Load += new EventHandler(RadComboBox1_Load);
}
protected void RadComboBox1_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// Ensure the static items are already bound before assigning
// new data to the DataSource property
RadComboBox1.DataBind();
var departments = new[] {
new { DeptID = 1, Abbr = "ACME", Name = "ACME Corporation" },
new { DeptID = 2, Abbr = "MSFT", Name = "Microsoft Corporation" },
new { DeptID = 3, Abbr = "GOOG", Name = "Google, Inc" }
};
RadComboBox1.DataSource = departments;
RadComboBox1.DataBind();
}
}
}
Hope that helps!

Resources