I'm implementing a messaging system in my program. It functions just like e-mail except that it is entirely contained within the system.
I was wondering if anyone has seen an e-mail control template that I could modify. It would have stuff like an inbox, message viewing and message sending parts.
I would just rewire the mail sending & receiving parts to my hook up to my tables.
Thanks!
Edit:
Ok I didn't realize I wrote so much. Make sure you credit Biff_MaGriff if you use this. :D
Tech is .net 3.5 with SubSonic 3.0
The rest is in my answer.
Should look like this in the end. (Minus all my cut outs)
web.config
<pages>
<controls>
...
<add tagPrefix="cc" tagName="MessageFolder" src="~/UserControls/Messages/MessageFolder/MessageFolder.ascx"/>
<add tagPrefix="cc" tagName="MessageView" src="~/UserControls/Messages/MessageView/MessageView.ascx"/>
<add tagPrefix="cc" tagName="MessageCompose" src="~/UserControls/Messages/MessageCompose/MessageCompose.ascx"/>
<add tagPrefix="cc" tagName="MessageBox" src="~/UserControls/Messages/MessageBox/MessageBox.ascx"/>
...
</controls>
<pages>
App_Code/IMessageFolder.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
/// Summary description for IMessageFolder
/// </summary>
public interface IMessageFolder
{
int? MessageID { get; }
}
App_Code/CustomDataViews.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.Linq;
using System.Linq;
using System.Web;
/// <summary>
/// Summary description for CustomDataViews
/// </summary>
public class CustomDataViews
{
//Subsonic db
static VAC.Data.VACDB db = new VAC.Data.VACDB();
public class MessageQuery
{
public class Message
{
public int MessageID { get; set; }
public string FromUser { get; set; }
public string ToUser { get; set; }
public DateTime SentDate { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
public bool IsDeletedSender { get; set; }
public bool IsDeletedRecipient { get; set; }
public bool IsRead { get; set; }
}
public enum MailType { ReceivedMail, SentMail };
public Message[] GetMessages(MailType mt, bool showDeleted)
{
List<Message> myMessages = new List<Message>();
foreach (var v in (from m in db.Messages
where (mt == MailType.ReceivedMail ? m.ToUserID : m.FromUserID) == Common.CurrentUserID
&& (showDeleted || !(mt == MailType.ReceivedMail ? m.IsDeletedRecipient : m.IsDeletedSender))
orderby m.SentDate descending
select m))
{
Message mess = new Message();
mess.MessageID = v.MessageID;
mess.FromUser = (from u in db.Users where u.UserID == v.FromUserID select u.UserName).First();
mess.ToUser = (from u in db.Users where u.UserID == v.ToUserID select u.UserName).First();
mess.SentDate = v.SentDate;
mess.Subject = v.Subject;
mess.Body = v.Body;
mess.IsDeletedSender = v.IsDeletedSender;
mess.IsDeletedRecipient = v.IsDeletedRecipient;
mess.IsRead = v.IsRead;
myMessages.Add(mess);
}
return myMessages.ToArray();
}
public Message GetMessage(int MessageID)
{
var myMessage = (from m in db.Messages where m.MessageID == MessageID select m);
if (myMessage.Count() == 1)
{
var v = myMessage.First();
Message mess = new Message();
mess.MessageID = v.MessageID;
mess.FromUser = (from u in db.Users where u.UserID == v.FromUserID select u.UserName).First();
mess.ToUser = (from u in db.Users where u.UserID == v.ToUserID select u.UserName).First();
mess.SentDate = v.SentDate;
mess.Subject = v.Subject;
mess.Body = v.Body;
return mess;
}
else
return null;
}
}
}
App_Code/Common.cs
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.SessionState;
using System.Web.Configuration;
using System.Data;
using System.Text;
using System.Collections;
using System.Globalization;
using System.Linq;
/// <summary>
/// Summary description for Common
/// </summary>
public class Common
{
/// <summary>
/// Retrieves the index of the column from the gridview. Returns -1 if not found.
/// </summary>
/// <param name="gv"></param>
/// <param name="columnName"></param>
/// <returns></returns>
static public int GetColumnIndex(GridView gv, string columnName)
{
int returnMe = -1;
for (int i = 0; i < gv.Columns.Count; i++)
{
if (gv.Columns[i].HeaderText == columnName)
{
returnMe = i;
break;
}
}
return returnMe;
}
//Colours for gridviews
static public string BGColourRed = "#FF8888";
static public string BGColourRedAlternate = "#FF0000";
static public string BGColourBlue = "#AAAAFF";
static public string BGColourBlueAlternate = "#4444FF";
static public string BGColourGreen = "#2bf053";
static public string BGColourGreenAlternate = "#27c319";
static public string BGColourOrange = "#FFA365";
static public string BGColourOrangeAlternate = "#FF6600";
static public string NormalBGColour(object sender)
{
return "#" +
((GridView)sender).RowStyle.BackColor.R.ToString("X") +
((GridView)sender).RowStyle.BackColor.G.ToString("X") +
((GridView)sender).RowStyle.BackColor.B.ToString("X");
}
static public string AlternateBGColour(object sender)
{
return "#" +
((GridView)sender).AlternatingRowStyle.BackColor.R.ToString("X") +
((GridView)sender).AlternatingRowStyle.BackColor.G.ToString("X") +
((GridView)sender).AlternatingRowStyle.BackColor.B.ToString("X");
}
static public string SelectedBGColour(object sender)
{
string selectedBGColour = "#165EA9";
if (!((GridView)sender).SelectedRowStyle.BackColor.IsEmpty)
{
selectedBGColour = "#" +
((GridView)sender).SelectedRowStyle.BackColor.R.ToString("X") +
((GridView)sender).SelectedRowStyle.BackColor.G.ToString("X") +
((GridView)sender).SelectedRowStyle.BackColor.B.ToString("X");
}
return selectedBGColour;
}
/// <summary>
/// Gridview RowDataBound extension.
/// Allows row selection by clicking on a row and highlights the row in yellow on the mouse hover.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
static public void GridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.DataItemIndex == -1)
return;
//e.Row.Attributes.Add("onclick", ((GridView)sender).Page.ClientScript.GetPostBackEventReference((GridView)sender, "Select$" + e.Row.RowIndex.ToString(), false));
string selectedBGColour = SelectedBGColour(sender);
string normalBGColour = NormalBGColour(sender);
string alternateBGColour = AlternateBGColour(sender);
ApplyStylingToRow(e.Row, selectedBGColour, normalBGColour, alternateBGColour);
}
static public void ApplyStylingToRow(GridViewRow row, string selectedBGColour, string normalBGColour, string alternateBGColour)
{
AppendAttribute(row, "onMouseOver",
"this.style.cursor='pointer'; this.style.background='yellow';");
AppendAttribute(row, "onMouseOut",
"this.style.background='" + ((row.RowState & DataControlRowState.Selected) == DataControlRowState.Selected ? selectedBGColour :
(row.RowState & DataControlRowState.Alternate) == DataControlRowState.Alternate ? alternateBGColour : normalBGColour) + "';");
}
static public void GridViewAddRowClick(GridView gv, GridViewRow row, bool isRender)
{
AppendAttribute(row, "onclick", gv.Page.ClientScript.GetPostBackEventReference(gv, "Select$" + row.RowIndex.ToString(), isRender) + ";");
/*
for (int i = 0; i < gv.Columns.Count; i++)
if (!string.IsNullOrEmpty(gv.Columns[i].HeaderText) && row.Cells.Count > 1)
AppendAttribute(row.Cells[i], "onclick", gv.Page.ClientScript.GetPostBackEventReference(gv, "Select$" + row.RowIndex.ToString(), isRender) + ";");
* */
}
static public void GridViewRowClick_Render(GridView gv)
{
foreach (GridViewRow row in gv.Rows)
if (row.RowType == DataControlRowType.DataRow)
GridViewAddRowClick(gv, row, true);
gv.Page.ClientScript.RegisterForEventValidation(gv.UniqueID);
}
/// <summary>
/// Hides a column on a gridview.
/// </summary>
/// <param name="gv"></param>
/// <param name="columnIndex"></param>
static public void HideColumn(GridView gv, int columnIndex)
{
if (gv.HeaderRow != null)
gv.HeaderRow.Cells[columnIndex].Style.Add("display", "none");
foreach (GridViewRow row in gv.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
row.Cells[columnIndex].Style.Add("display", "none");
}
}
/// <summary>
/// Registers javascript to be run.
/// </summary>
/// <param name="con"></param>
/// <param name="script"></param>
static public void RegisterStartupScript(object con, string script)
{
RegisterStartupScript((Control)con, script);
}
/// <summary>
/// Capitalizes the beginning of strings
/// </summary>
/// <param name="strText"></param>
public static string InitCap(string strText)
{
return new CultureInfo("en").TextInfo.ToTitleCase(strText.ToLower());
}
/// <summary>
/// Registers javascript to be run.
/// </summary>
/// <param name="con"></param>
/// <param name="script"></param>
static public void RegisterStartupScript(Control con, string script)
{
ScriptManager sm = ScriptManager.GetCurrent(con.Page);
if (sm != null)
ScriptManager.RegisterStartupScript(con, con.GetType(), Guid.NewGuid().ToString(), script, true);
else
con.Page.ClientScript.RegisterStartupScript(typeof(Page), Guid.NewGuid().ToString(), script, true);
}
/// <summary>
/// Registers a javascript file to be included in the page.
/// </summary>
/// <param name="con"></param>
/// <param name="url"></param>
static public void RegisterClientScriptInclude(Control con, string url)
{
ScriptManager sm = ScriptManager.GetCurrent(con.Page);
if (sm != null)
ScriptManager.RegisterClientScriptInclude(con, con.GetType(), Guid.NewGuid().ToString(), System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath + url);
else
con.Page.ClientScript.RegisterClientScriptInclude(typeof(Page), Guid.NewGuid().ToString(), System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath + url);
}
public static int CurrentUserID { get { return (from u in new VAC.Data.VACDB().Users where u.UserName == HttpContext.Current.User.Identity.Name select u.UserID).First(); } }
public class MessageComposeEventArgs : EventArgs
{
public int? SendToUserID { get; set; }
public string Subject { get; set; }
public MessageComposeEventArgs()
{
}
public MessageComposeEventArgs(int SendToUserID)
{
this.SendToUserID = SendToUserID;
}
public MessageComposeEventArgs(int SendToUserID, string Subject)
{
this.SendToUserID = SendToUserID;
this.Subject = Subject;
}
}
}
App_Code/ExtendedCommandField.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
/// <summary>
/// An extended <see cref="CommandField"/> that allows deletions
/// to be confirmed by the user.
/// </summary>
public class ExtendedCommandField : CommandField
{
/// <summary>
/// Initialize the cell.
/// </summary>
public override void InitializeCell(DataControlFieldCell cell,
DataControlCellType cellType, DataControlRowState rowState, int rowIndex)
{
base.InitializeCell(cell, cellType, rowState, rowIndex);
if (!string.IsNullOrEmpty(this.DeleteConfirmationText) && this.ShowDeleteButton)
{
foreach (Control control in cell.Controls)
{
IButtonControl button = control as IButtonControl;
if (button != null && button.CommandName == "Delete")
// Add delete confirmation
((WebControl)control).Attributes.Add("onclick", string.Format
("if (!confirm('{0}')) return false;", this.DeleteConfirmationText));
}
}
}
#region DeleteConfirmationText
/// <summary>
/// Delete confirmation text.
/// </summary>
[Category("Behavior")]
[Description("The text shown to the user to confirm the deletion.")]
public string DeleteConfirmationText
{
get { return this.ViewState["DeleteConfirmationText"] as string; }
set { this.ViewState["DeleteConfirmationText"] = value; }
}
#endregion
}
~/UserControls/Messages/MessageFolder/MessageFolder.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeFile="MessageFolder.ascx.cs"
Inherits="UserControls_Messages_MessageFolder_MessageFolder" %>
<asp:UpdatePanel ID="up1" runat="server">
<ContentTemplate>
<asp:HiddenField ID="hfMessageID" runat="server" />
<asp:Button ID="butRefresh" runat="server" Text="Check for new Messages" /><asp:Button
ID="butCompose" runat="server" Text="Compose New Message" OnClick="butCompose_Click" /><asp:CheckBox
AutoPostBack="true" ID="cbShowDeleted" runat="server" Text="Show Deleted Messages"
OnCheckedChanged="cbShowDeleted_CheckChanged" />
<asp:GridView ID="gvMessages" runat="server" DataKeyNames="MessageID" AutoGenerateColumns="false"
OnRowDataBound="gvMessages_RowDataBound" OnSelectedIndexChanged="gvMessages_SelectedIndexChanged"
OnRowDeleting="gvMessages_RowDeleting" Width="100%" Style="float: left;">
<Columns>
<asp:BoundField DataField="MessageID" InsertVisible="false" />
<cc:ExtendedCommandField DeleteConfirmationText="Are you certain you wish to delete this record?"
DeleteText="Delete" ShowDeleteButton="true" />
<asp:BoundField DataField="FromUser" HeaderText="From" />
<asp:BoundField DataField="ToUser" HeaderText="To" />
<asp:TemplateField>
<HeaderTemplate>
Sent Date</HeaderTemplate>
<ItemTemplate>
<asp:Label ID="lbl1" runat="server" Text='<%# Bind("SentDate") %>' Style="white-space: nowrap;" /></ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Subject" HeaderText="Subject" ItemStyle-Width="100%" />
</Columns>
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
I ended up creating my own user control. If anyone is interested message and I'll post the details.
Edit:
Ok I didn't realize I wrote so much. Make sure you credit Biff_MaGriff if you use this. :D
Tech is .net 3.5 with SubSonic 3.0
Should look like this in the end.
Hmm, can't post over 30k characters...
Continued from above.
~/UserControls/Messages/MessageFolder/MessageFolder.ascx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class UserControls_Messages_MessageFolder_MessageFolder : System.Web.UI.UserControl, IMessageFolder
{
private static int IDCOLUMNINDEX = 0;
private static int DELETECOLUMNINDEX = 1;
private static int FROMCOLUMNINDEX = 2;
private static int TOCOLUMNINDEX = 3;
public event SelectedIndexChangedEventHandler SelectedIndexChanged;
public delegate void SelectedIndexChangedEventHandler(object sender, EventArgs e);
public event ComposeMessageEventHandler ComposeMessage;
public delegate void ComposeMessageEventHandler(object sender, Common.MessageComposeEventArgs e);
VAC.Data.VACDB db = new VAC.Data.VACDB();
public int? MessageID
{
get
{
int id;
if (int.TryParse(hfMessageID.Value, out id))
return id;
else
return null;
}
}
public CustomDataViews.MessageQuery.MailType MailType { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
if (MailType == CustomDataViews.MessageQuery.MailType.SentMail)
{
butCompose.Visible = false;
}
Refresh();
}
public void Refresh()
{
gvMessages.DataSource = new CustomDataViews.MessageQuery().GetMessages(MailType, cbShowDeleted.Checked);
gvMessages.DataBind();
Common.HideColumn(gvMessages, IDCOLUMNINDEX);
if (MailType == CustomDataViews.MessageQuery.MailType.ReceivedMail)
Common.HideColumn(gvMessages, TOCOLUMNINDEX);
else
Common.HideColumn(gvMessages, FROMCOLUMNINDEX);
}
protected void gvMessages_RowDataBound(object sender, GridViewRowEventArgs e)
{
Common.GridView_RowDataBound(sender, e);
if (e.Row.RowType == DataControlRowType.DataRow)
{
CustomDataViews.MessageQuery.Message dataItem = ((CustomDataViews.MessageQuery.Message)e.Row.DataItem);
if (dataItem.IsDeletedSender && MailType == CustomDataViews.MessageQuery.MailType.SentMail
|| dataItem.IsDeletedRecipient && MailType == CustomDataViews.MessageQuery.MailType.ReceivedMail)
{
foreach (TableCell tc in e.Row.Cells)
tc.Enabled = false;
e.Row.Cells[DELETECOLUMNINDEX].Enabled = true;
((LinkButton)e.Row.Cells[DELETECOLUMNINDEX].Controls[0]).Text = "Undelete";
((LinkButton)e.Row.Cells[DELETECOLUMNINDEX].Controls[0]).Attributes.Clear();
}
if (!dataItem.IsRead && MailType == CustomDataViews.MessageQuery.MailType.ReceivedMail)
{
//colouring for initial load
if ((e.Row.RowState & DataControlRowState.Alternate) == DataControlRowState.Alternate)
e.Row.BackColor = System.Drawing.ColorTranslator.FromHtml(Common.BGColourGreenAlternate);
else
e.Row.BackColor = System.Drawing.ColorTranslator.FromHtml(Common.BGColourGreen);
//colouring for onmouse out
Common.ApplyStylingToRow(e.Row, Common.SelectedBGColour(sender), Common.BGColourGreen, Common.BGColourGreenAlternate);
}
}
if (ScriptManager.GetCurrent(this.Page).IsInAsyncPostBack && e.Row.RowType == DataControlRowType.DataRow)
Common.GridViewAddRowClick(gvMessages, e.Row, false);
}
protected void gvMessages_SelectedIndexChanged(object sender, EventArgs e)
{
hfMessageID.Value = gvMessages.SelectedValue != null ? gvMessages.SelectedValue.ToString() : "";
if (MailType == CustomDataViews.MessageQuery.MailType.ReceivedMail)
{
var mess = (from m in db.Messages where m.MessageID == MessageID.Value select m);
if (mess.Count() == 1)
{
var message = mess.First();
message.IsRead = true;
message.Save();
}
}
if (this.SelectedIndexChanged != null)
SelectedIndexChanged(this, new EventArgs());
this.Refresh();
}
protected void gvMessages_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
int id;
if (int.TryParse(((GridView)sender).Rows[e.RowIndex].Cells[IDCOLUMNINDEX].Text, out id))
{
var message = (from m in db.Messages where m.MessageID == id select m).First();
if (!message.IsDeletedRecipient && MailType == CustomDataViews.MessageQuery.MailType.ReceivedMail)
message.IsDeletedRecipient = true;
else
message.IsDeletedRecipient = false;
message.Save();
if (!message.IsDeletedSender && MailType == CustomDataViews.MessageQuery.MailType.SentMail)
message.IsDeletedSender = true;
else
message.IsDeletedSender = false;
message.Save();
gvMessages.SelectedIndex = -1;
gvMessages_SelectedIndexChanged(gvMessages, new EventArgs());
}
Refresh();
}
protected override void Render(HtmlTextWriter writer)
{
Common.GridViewRowClick_Render(gvMessages);
base.Render(writer);
}
protected void butCompose_Click(object sender, EventArgs e)
{
if (this.ComposeMessage != null)
{
this.ComposeMessage(this, new Common.MessageComposeEventArgs());
}
}
protected void cbShowDeleted_CheckChanged(object sender, EventArgs e)
{
Refresh();
}
}
MessageCompose.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeFile="MessageCompose.ascx.cs"
Inherits="UserControls_Messages_MessageCompose_MessageCompose" %>
<div>
<table style="width: 100%;">
<tr>
<td>
<asp:Label ID="Label1" runat="server" Text="To :" />
</td>
<td style="width:100%">
<asp:DropDownList ID="ddlToUser" runat="server" AppendDataBoundItems="true" DataSourceID="odsUsers"
DataTextField="UserName" DataValueField="UserID">
<asp:ListItem Text="--Select--" Value="" />
</asp:DropDownList>
<asp:ObjectDataSource ID="odsUsers" runat="server" SelectMethod="GetUsers" TypeName="CustomDataViews+UserListQuery">
</asp:ObjectDataSource>
<asp:RequiredFieldValidator ID="rfv1" runat="server" Text="*" ControlToValidate="ddlToUser"
ValidationGroup="Compose" />
</td>
</tr>
<tr>
<td>
<asp:Label ID="Label2" runat="server" Text="Subject :" />
</td>
<td style="padding: 1px 5px 1px 1px">
<asp:TextBox ID="tbSubject" runat="server" Width="100%" />
</td>
</tr>
<tr>
<td colspan="2" style="padding: 1px 5px 1px 1px">
<asp:TextBox ID="tbBody" runat="server" TextMode="MultiLine" Style="width: 100%"
Rows="20" />
</td>
</tr>
<tr>
<td colspan="2">
<table width="100%">
<tr>
<td align="center">
<asp:Label ID="lblMessageSentText" runat="server" Text="Your message was sent." CssClass="info" Visible="false" />
</td>
<td align="right">
<asp:Button ID="butSend" runat="server" Text="Send" OnClick="butSend_Click" ValidationGroup="Compose"
/>
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
MessageCompose.ascx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using VAC.Data;
public partial class UserControls_Messages_MessageCompose_MessageCompose : System.Web.UI.UserControl
{
public event MessageSentEventHandler MessageSent;
public delegate void MessageSentEventHandler(object sender, EventArgs e);
public int? SendToUserID
{
set
{
if (ddlToUser.Items.FindByValue(value.HasValue ? value.Value.ToString() : "") != null)
ddlToUser.SelectedValue = value.HasValue ? value.Value.ToString() : "";
else
Common.RegisterStartupScript(this, "alert('Error : You are unauthorized to respond to this message.');");
}
}
public string SendToSubject
{
set
{
tbSubject.Text = "RE: " + value;
}
}
protected void Page_Load(object sender, EventArgs e)
{
lblMessageSentText.Visible = false;
}
private static string SENTMESSAGETEXT = "Your message was sent at {0} to {1}.";
protected void butSend_Click(object sender, EventArgs e)
{
Message m = new Message();
m.Body = tbBody.Text;
m.FromUserID = Common.CurrentUserID;
m.IsRead = false;
m.SentDate = DateTime.Now;
m.Subject = tbSubject.Text;
int tid;
if (int.TryParse(ddlToUser.SelectedValue, out tid))
m.ToUserID = tid;
m.Save();
lblMessageSentText.Text = string.Format(SENTMESSAGETEXT, DateTime.Now.ToString(), ddlToUser.SelectedItem.Text);
lblMessageSentText.Visible = true;
ddlToUser.SelectedValue = null;
tbSubject.Text = "";
tbBody.Text = "";
if (this.MessageSent != null)
MessageSent(this, new EventArgs());
}
}
MessageView.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeFile="MessageView.ascx.cs" Inherits="UserControls_Messages_MessageView_MessageView" %>
<asp:HiddenField ID="hfMessageID" runat="server" />
<div style="border-style: solid;">
<div style="font-size: x-large; padding: 10px 10px 10px 10px;">
<asp:Label ID="lblSubject" runat="server" Text='<%# Bind("Subject") %>' /></div>
<div style="background-color: lightblue;">
<table>
<tr>
<td>
<asp:Label ID="Label1" runat="server" Text="From :" />
</td>
<td>
<asp:Label ID="lblFromUser" runat="server" Text='<%# Bind("FromUser") %>' />
</td>
</tr>
<tr>
<td>
<asp:Label ID="Label2" runat="server" Text="To :" />
</td>
<td>
<asp:Label ID="lblToUser" runat="server" Text='<%# Bind("ToUser") %>' />
</td>
</tr>
<tr>
<td>
<asp:Label ID="Label3" runat="server" Text="Sent :" />
</td>
<td>
<asp:Label ID="lblSentDate" runat="server" Text='<%# Bind("SentDate") %>' />
</td>
</tr>
</table>
</div>
<div style="padding: 10px 10px 10px 10px">
<asp:Label ID="lblBody" runat="server" Text='<%# Bind("Body") %>' />
</div>
<div style="padding: 10px 10px 10px 10px">
<asp:LinkButton ID="lbReply" runat="server" Text="Reply"
onclick="lbReply_Click" /></div>
</div>
MessageView.ascx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class UserControls_Messages_MessageView_MessageView : System.Web.UI.UserControl
{
public event ComposeMessageEventHandler ComposeMessage;
public delegate void ComposeMessageEventHandler(object sender, Common.MessageComposeEventArgs e);
public int? MessageID
{
get
{
int mid;
return int.TryParse(hfMessageID.Value, out mid) ? mid : new int?();
}
set
{
hfMessageID.Value = (value.HasValue) ? value.ToString() : "";
BindMessageView();
}
}
private void BindMessageView()
{
if (MessageID.HasValue)
{
CustomDataViews.MessageQuery.Message message = new CustomDataViews.MessageQuery().GetMessage(MessageID.Value);
this.Visible = true;
lblBody.Text = message.Body;
lblFromUser.Text = message.FromUser;
lblSentDate.Text = message.SentDate.ToString();
lblSubject.Text = message.Subject;
lblToUser.Text = message.ToUser;
}
else
{
this.Visible = false;
lblBody.Text = "";
lblFromUser.Text = "";
lblSentDate.Text = "";
lblSubject.Text = "";
lblToUser.Text = "";
}
}
protected void Page_Load(object sender, EventArgs e)
{
}
protected void lbReply_Click(object sender, EventArgs e)
{
var mess = (from m in new VAC.Data.VACDB().Messages where m.MessageID == MessageID select m);
if (mess.Count() == 1)
{
if (this.ComposeMessage != null)
this.ComposeMessage(this, new Common.MessageComposeEventArgs(mess.First().FromUserID, mess.First().Subject));
}
}
}
MessageBox.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeFile="MessageBox.ascx.cs" Inherits="UserControls_Messages_MessageBox_MessageBox" %>
<asp:UpdatePanel ID="up1" runat="server">
<ContentTemplate>
<h1>
Message Inbox</h1>
<cc:MessageFolder ID="mf1" runat="server" MailType="ReceivedMail" OnSelectedIndexChanged="SelectedMessageChanged"
OnComposeMessage="ComposeMessage" />
<h2>
Sent Messages</h2>
<cc:MessageFolder ID="mf2" runat="server" MailType="SentMail" OnSelectedIndexChanged="SelectedMessageChanged" />
<br />
<cc:MessageView ID="mv1" runat="server" OnComposeMessage="ComposeMessage" />
<br />
<cc:MessageCompose ID="mc1" runat="server" OnMessageSent="mc1_MessageSent" />
</ContentTemplate>
</asp:UpdatePanel>
MessageBox.ascx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class UserControls_Messages_MessageBox_MessageBox : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
mv1.MessageID = mf1.MessageID;
mc1.Visible = false;
}
}
protected void SelectedMessageChanged(object sender, EventArgs e)
{
mv1.MessageID = ((IMessageFolder)sender).MessageID;
mc1.Visible = false;
}
protected void ComposeMessage(object sender, Common.MessageComposeEventArgs e)
{
mc1.Visible = true;
mc1.DataBind();
if (e.SendToUserID.HasValue)
mc1.SendToUserID = e.SendToUserID;
if (!string.IsNullOrEmpty(e.Subject))
mc1.SendToSubject = e.Subject;
}
protected void mc1_MessageSent(object sender, EventArgs e)
{
mf2.Refresh();
}
}
Messages.aspx
<%# Page Title="" Language="C#" MasterPageFile="~/Templates/Patient.master" AutoEventWireup="true"
CodeFile="Messages.aspx.cs" Inherits="UI_Patient_Messages" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
<cc:MessageBox ID="mi1" runat="server" />
</asp:Content>
Messages.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class UI_Patient_Messages : BasePage
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
If you're willing to fork out some money, Telerik has a nice PanelBar control that looks just like Outlook. I believe the samples that ship with it are identical to the Outlook-like demo application on their site, so that would probably be a very quick and easy way to get started.
By Steve Danner:
Telerik has a nice PanelBar control that looks just like Outlook. I believe the samples that ship with it are identical to the Outlook-like demo application on their site, so that would probably be a very quick and easy way to get started.
FYI, The panelbar control is just a UI, it doesn't provide the messaging functionality. Of course, you can use it to make your messaging system look like outlook, but you still have to do the coding on your own.
Related
Checkbox list items have default "Text", "Value", "Enabled" and "Selected" properties.
I need to add an "ImageUrl" property to each item in my list.
I use this code:
foreach (Zone zn in ZonesList)
{
ListItem item = new ListItem(zn.Name, zn.Id.ToString());
item.Attributes.Add("ImageUrl", zn.Image );
item.Selected = false;
visitPlaceList.Items.Add(item);
}
visitPlaceList.DataBind();
but it still doesn't show any properties other than the defaults.
How can this be achieved?
A property does get added, but as a span element surrounding the input and label. It looks like this
<span imageurl="www.google.nl">
<input id="ctl00_mainContentPane_visitPlaceList_1" type="checkbox" name="ctl00$mainContentPane$visitPlaceList$1" />
<label for="ctl00_mainContentPane_visitPlaceList_1">Name 1</label>
</span>
So if you need it with jQuery, get the correct element.
<asp:CheckBoxList ID="visitPlaceList" runat="server" ClientIDMode="Static"></asp:CheckBoxList>
<script>
$("#visitPlaceList input").change(function () {
var imageurl = $(this).closest('span').attr('imageurl');
console.log(imageurl);
});
</script>
Very interesting question! It exposes the limitations that web controls sometimes have.
I believe the proper way to solve it is by creating a custom (web) control. It is far from trivial though especially since both ListItem and CheckBoxList are sealed classes.
It can also be solved by creating a user control (ascx). The following can be improved but you get the idea:
ImageCheckBoxList.ascx
<asp:Repeater ID="Repeater1" runat="server">
<HeaderTemplate>
<table>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<asp:CheckBox ID="CheckBox1" runat="server" /><asp:Image ID="Image1" runat="server" ImageUrl='<%# Eval("ImageUrl") %>' /><asp:Label ID="Label1" runat="server" AssociatedControlID="CheckBox1" Text='<%# Eval("Text") %>'></asp:Label>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
ImageCheckBoxList.ascx.cs
public partial class ImageCheckBoxList : System.Web.UI.UserControl
{
public IList<ImageListItem> Items { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Repeater1.DataSource = Items;
Repeater1.DataBind();
}
for (int i = 0; i < Repeater1.Items.Count; i++)
{
var checkBox = (CheckBox)Repeater1.Items[i].FindControl("CheckBox1");
if (checkBox != null)
{
Items[i].Checked = checkBox.Checked;
}
}
}
}
where ImageListItem is:
public class ImageListItem
{
public string Text { get; set; }
public string Value { get; set; }
public string ImageUrl { get; set; }
public bool Checked { get; set; }
public ImageListItem(string text, string value, string imageUrl)
{
Text = text;
Value = value;
ImageUrl = imageUrl;
Checked = false;
}
}
Here's how to use it in a Web Forms page:
ASPX
<%# Register TagPrefix="uc" TagName="ImageCheckBoxList" Src="ImageCheckBoxList.ascx" %>
<uc:ImageCheckBoxList ID="ImageCheckBoxList1" runat="server" />
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
Code-behind
protected void Page_Load(object sender, EventArgs e)
{
ImageCheckBoxList1.Items = new List<ImageListItem>()
{
new ImageListItem("Item 1", "Item1", "Images/1.png"),
new ImageListItem("Item 2", "Item2", "Images/2.png"),
new ImageListItem("Item 3", "Item3", "Images/3.png")
};
}
protected void Button1_Click(object sender, EventArgs e)
{
StringBuilder sb = new StringBuilder();
foreach (ImageListItem item in ImageCheckBoxList1.Items)
{
if (item.Checked)
{
sb.AppendLine($"{item.Text} with value {item.Value} is checked.");
}
}
Label1.Text = sb.ToString();
}
I am essentially trying to add some clickable way to delete or edit entries from my table. These entries are all saved on an access database which populates the table. My biggest problem is that I am unsure on how I can program the clickable method so that it saves which username I am trying to edit/delete. Any advice would be appreciated.
Relevant code:
main.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeFile="main.aspx.cs" Inherits="main" %>
<%# Reference Control="~/UserInfoBoxControl.ascx" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:PlaceHolder runat="server" ID="phUserInfoBox" />
</div>
<asp:Button id="login" runat="server" Text="edit profile" onclick="btnRegister_click" />
<asp:Button id="create" runat="server" Text="logout" onclick="btnLogout_click" />
</form>
</body>
</html>
main.aspx.cs
using System;
using System.Collections.Generic;
using System.Data.OleDb;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class main : System.Web.UI.Page
{
private OleDbConnection bookConn;
private OleDbCommand oleDbCmd = null;
private String connParam = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source='F:\test\Database21.accdb'; Persist Security Info=False;";
protected void Page_Load(object sender, EventArgs e)
{
{
OleDbDataReader reader;
bookConn = new OleDbConnection(connParam);
bookConn.Open();
oleDbCmd = new OleDbCommand("SELECT user_name, fname, lname FROM profiles",bookConn);
reader = oleDbCmd.ExecuteReader();
while (reader.Read())
{
UserInfoBoxControl MyUserInfoBoxControl =(UserInfoBoxControl)LoadControl("UserInfoBoxControl.ascx");
phUserInfoBox.Controls.Add(MyUserInfoBoxControl);
MyUserInfoBoxControl.UserName = reader.GetString(0);
MyUserInfoBoxControl.FirstName = reader.GetString(1);
MyUserInfoBoxControl.LastName = reader.GetString(2);
}
bookConn.Close();
}
}
protected void btnRegister_click(object sender, EventArgs e)
{
Response.Redirect("myprofile.aspx");
}
protected void btnLogout_click(object sender, EventArgs e)
{
Response.Redirect("index.aspx");
}
}
UserInfoBoxControl.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeFile="UserInfoBoxControl.ascx.cs" Inherits="UserInfoBoxControl" %>
<table>
<tr>
<th>UserName</th>
<th>First Name</th>
<th>Last Name</th>
</tr>
<tr>
<td><%= this.UserName %> </td>
<td><%= this.FirstName %></td>
<td><%= this.LastName %></td>
</tr>
</table>
UserInfoBoxControl.ascx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class UserInfoBoxControl : System.Web.UI.UserControl
{
private string userName;
private string fname;
private string lname;
public string UserName
{
get { return userName; }
set { userName = value; }
}
public string FirstName
{
get { return fname; }
set { fname = value; }
}
public string LastName
{
get { return lname; }
set { lname = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
You'll want to use model binding where you define a class type to show in the grid.
http://www.asp.net/web-forms/overview/presenting-and-managing-data/model-binding/updating-deleting-and-creating-data
Then you'll specify in your gridview with commands to update/delete/etc your records. In those methods you'll get the applicable info and delete.
Ex grid:
<asp:GridView runat="server" ID="studentsGrid"
ItemType="ContosoUniversityModelBinding.Models.Student" DataKeyNames="StudentID"
SelectMethod="studentsGrid_GetData"
UpdateMethod="studentsGrid_UpdateItem" DeleteMethod="studentsGrid_DeleteItem"
AutoGenerateEditButton="true" AutoGenerateDeleteButton="true"
AutoGenerateColumns="false">
and then notice how the id is passed in:
public void studentsGrid_DeleteItem(int studentID)
{
using (SchoolContext db = new SchoolContext())
{
var item = new Student { StudentID = studentID };
db.Entry(item).State = EntityState.Deleted;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
ModelState.AddModelError("",
String.Format("Item with id {0} no longer exists in the database.", studentID));
}
}
}
If this is your first time with web forms, I'd honestly look at going the MVC route and using MVC Scaffolding. You cannot use the Access database though with entity framework you'd need to use your OLEDB code directly like you did above (or not use access if that's an option)
I ended up figuring it out. All I did was add a button in the web user control box and in the code behind created a new session variable.
UserInfoBoxControl.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeFile="UserInfoBoxControl.ascx.cs" Inherits="UserInfoBoxControl" %>
<table>
<tr>
<th>UserName</th>
<th>First Name</th>
<th>Last Name</th>
</tr>
<tr>
<td><%= this.UserName %> </td>
<td><%= this.FirstName %></td>
<td><%= this.LastName %> <asp:Button id="login" runat="server" Text="edit user" onclick="btnEdit_click" /></td>
</tr>
</table>
UserInfoBoxControl.ascx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class UserInfoBoxControl : System.Web.UI.UserControl
{
private string userName;
private string fname;
private string lname;
public string UserName
{
get { return userName; }
set { userName = value; }
}
public string FirstName
{
get { return fname; }
set { fname = value; }
}
public string LastName
{
get { return lname; }
set { lname = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnEdit_click(object sender, EventArgs e)
{
Session["UserNameMod"] = userName;
Response.Redirect("userinfo.aspx");
}
}
I used User Control and Placeholder when added uc to place holder. Count place holder is 0. And then clicking the button on uc does not fire any code. All viewstate is ok, and I don't know what happened.
I used this class to add user control:
public abstract class MasterControl : System.Web.UI.UserControl
{
protected System.Web.UI.WebControls.PlaceHolder PlaceHolder1;
public void Initial(bool postback =true)
{
this.CurrenetContorl = (BaseUserControl)this.LoadControl(this.CurrentPath);
this.CurrenetContorl.PostBack = this.FristLoad ? !FristLoad : postback;
this.CurrenetContorl.PreviousControl = this.PreviousControl;
this.CurrenetContorl.CurrentControl = this.CurrentPath;
if (!this.PlaceHolder1.Controls.OfType<BaseUserControl>().Any( x=> x.ID.Equals(this.CurrenetContorl.ID)))
{
this.PlaceHolder1.Controls.Add(this.CurrenetContorl);
this.FristLoad = false;
}
}
private BaseUserControl _currentcontrol;
public BaseUserControl CurrenetContorl
{
get { return _currentcontrol; }
set {
_currentcontrol = value;
if (_currentcontrol == null) return;
_currentcontrol.Redirecting += CurrentControlRedirecting;
_currentcontrol.ID = this.GetId;
}
}
private bool FristLoad = false;
void CurrentControlRedirecting(string url)
{
var ctrl= this.PlaceHolder1.Controls.OfType<BaseUserControl>().FirstOrDefault();
if (ctrl != null)
{
this.PlaceHolder1.Controls.Remove(ctrl);
this.PreviousControl = ctrl.GetType().Name;
}
this.CurrnetUrl = url;
this.Initial(false);
}
public string CurrnetUrl
{
get
{
return this.ViewState["currentUrl"].ToString();
}
set
{
var temp = "";
if (value.StartsWith("/"))
{
temp = "http://"+Request.Url.Authority +value;
}
this.ViewState["currentUrl"] = temp;
this.CurrentPath = this.GetPath();
}
}
private string GetPath()
{
var uri = new Uri(this.CurrnetUrl);
return uri.AbsolutePath;
}
public string PreviousControl
{
get
{
if (this.ViewState["_previousControl"] == null)
this.ViewState["_previousControl"] = string.Empty;
return this.ViewState["_previousControl"].ToString();
}
set
{
this.ViewState["_previousControl"] = value;
}
}
protected string CurrentPath
{
get
{
if (this.ViewState["_currentpath"] == null)
this.ViewState["_currentpath"] = string.Empty;
return this.ViewState["_currentpath"].ToString();
}
set
{
this.ViewState["_currentpath"] = value;
}
}
private string GetId
{
get
{
if (this.ViewState["ControlId"] == null)
this.ViewState["ControlId"] = Guid.NewGuid();
return this.ViewState["ControlId"].ToString();
}
}
public void Redirect(string url)
{
this.CurrentControlRedirecting(url);
}
public void LoadUrl(string url)
{
this.CurrnetUrl = url;
this.CurrenetContorl = (BaseUserControl)this.LoadControl(this.CurrentPath);
this.FristLoad = true;
this.PreviousControl = "";
}
}
public abstract class BaseUserControl : System.Web.UI.UserControl
{
public string PreviousControl
{
get
{
if (this.ViewState["precontrol"] == null)
this.ViewState["precontrol"] = string.Empty;
return this.ViewState["precontrol"].ToString();
}
set
{
this.ViewState["precontrol"] = value;
}
}
public string CurrentControl
{
get
{
if (this.ViewState["ccontrol"] == null)
this.ViewState["ccontrol"] = string.Empty;
return this.ViewState["ccontrol"].ToString();
}
set
{
this.ViewState["ccontrol"] = value;
}
}
public delegate void RedirectHandler(string url);
public event RedirectHandler Redirecting;
public bool PostBack
{
get
{
if (this.ViewState["_postBack"] == null)
this.ViewState["_postBack"] = false;
return this.ViewState["_postBack"].ToString().ToBol();
}
set
{
this.ViewState["_postBack"] = value;
}
}
public void Redirect(string url)
{
this.Redirecting(url);
}
}
public abstract class BaseUserControl<T> : BaseUserControl
{
public virtual void GetDataFromControl(T obj)
{
this.TryUpdateModel(obj);
}
public virtual void LoadControl(T obj)
{
this.TryBindModel(obj);
}
}
main.ascx code
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Telerik.Web.UI;
namespace WebApplication1
{
public partial class Main : MasterControl
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
}
}
protected void RadMenu1_ItemClick(object sender, Telerik.Web.UI.RadMenuEventArgs e)
{
if (e.Item.Selected != null)
{
this.Redirect(e.Item.Value);
}
}
}
}
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="Main.ascx.cs" Inherits="WebApplication1.Main" %>
<%# Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>
<link href="Main.css" rel="stylesheet" />
<div class="RadMenu_WebBlue">
<telerik:RadMenu ID="RadMenu1" runat="server" OnItemClick="RadMenu1_ItemClick" EnableEmbeddedSkins="False" >
<Items>
<telerik:RadMenuItem runat="server" Text="مطالب" >
<Items>
<telerik:RadMenuItem runat="server" Text="ایجاد مطلب جدید" Value="/CreatePost.ascx" />
<telerik:RadMenuItem runat="server" Text="ارشیو مطالب" Value="/ArchivePost.ascx"></telerik:RadMenuItem>
</Items>
</telerik:RadMenuItem>
<telerik:RadMenuItem runat="server" Text="تغییر رمز عبور" Value="/changePassword.ascx"></telerik:RadMenuItem>
</Items>
</telerik:RadMenu>
</div>
<asp:PlaceHolder EnableViewState="True" ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
You should initialize usercontrol in main page
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
}
this.Initialize();
}
I have a repeater control in a user control. The repeater control has a label and a textbox. A new row is added in repeater control on the click of a button. If i add one row and enter some value in textBox and then again add a new row in the repeater control the value entered in the textbox of first row gets lost.
Can anyone help me out how to retain the value of textbox after postback.
You are losing it because you do not have a If not IsPostBack wrapped around the code that sets the value of the textbox.
So every time you execute the page the value is being reset. Wrap the code that sets the value around ispostback and the new value will not be overridden.
if (!Page.IsPostBack) { // set value }
You may get help from the following link:
http://ranafaisal.wordpress.com/2009/02/17/dynamically-adding-removing-textboxes-in-aspnet-repeater/
I have tried myself and found a solution:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace RepeaterTest
{
public class Car
{
private string _year;
private string _make;
private string _model;
public string Year
{
get
{
return _year;
}
set
{
_year = value;
}
}
public string Make {
get { return _make; }
set { _make=value;}
}
public string Model
{
get { return _model; }
set { _model = value; }
}
public Car(string year,string make,string model){
_year = year;
_make = make;
_model = model;
}
public Car(){
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Collections;
namespace RepeaterTest
{
public class Cars:CollectionBase
{
public int Add(Car car) {
return List.Add(car);
}
}
}
in code behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace RepeaterTest
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack) {
Cars cars = new Cars();
Car c1 = new Car("2011", "Marcedez", "Marcedez");
Car c2 = new Car("2012", "BMW", "135i");
cars.Add(c1);
cars.Add(c2);
Repeater1.DataSource = cars;
Repeater1.DataBind();
}
}
protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "Add") {
//Car carLastEntered = new Car();
Cars cars = new Cars();
foreach (RepeaterItem item in Repeater1.Items) {
Car car = new Car();
car.Year = ((TextBox)(item.FindControl("txtYear"))).Text;
car.Make = ((TextBox)(item.FindControl("txtMake"))).Text;
car.Model = ((TextBox)(item.FindControl("txtModel"))).Text;
cars.Add(car);
//carLastEntered = car;
}
//cars.Add(carLastEntered);
Repeater1.DataSource = cars;
Repeater1.DataBind();
}
}
}
}
in aspx:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="RepeaterTest.WebForm1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Repeater ID="Repeater1" runat="server"
onitemcommand="Repeater1_ItemCommand">
<HeaderTemplate>
<table cellpadding="0" cellspacing="5">
<tr style="padding-top: 5px;">
<td colspan="6">
<asp:Label ID="lblInstructions" runat="server" Text="Add your cars here:" />
</td>
</tr>
<tr runat="server" id="trHeader" style="font-weight: bold;">
<td>Year</td>
<td>Make</td>
<td>Model</td>
<td></td>
<td></td>
<td></td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><asp:TextBox ID="txtYear" runat="server" Width="65"
Text='<%#DataBinder.Eval(Container.DataItem, "Year")%>' /></td>
<td><asp:TextBox ID="txtMake" runat="server" Width="70"
Text='<%#DataBinder.Eval(Container.DataItem, "Make")%>' /></td>
<td><asp:TextBox ID="txtModel" runat="server" Width="70"
Text='<%#DataBinder.Eval(Container.DataItem, "Model")%>' /></td>
</tr>
</ItemTemplate>
<FooterTemplate>
<tr style="padding-top: 5px;">
<td colspan="6">
<asp:Button ID="btnAdd" runat="server"
Text="Add Car" CommandName="Add" />
</td>
</tr>
</table>
</FooterTemplate>
</asp:Repeater>
</div>
</form>
</body>
</html>
Hope this helps. Thanks.
I am trying to populate a repeater containing a label and a RadioButtonList in an ASP.NET webform to make a small quiz.
These are the classes I am using:
public class Option
{
private string _body;
private bool? _isCorrect;
#region properties
public string Body
{
get { return _body; }
}
public bool? IsCorrect
{
get { return _isCorrect; }
}
#endregion
#region constructors
public Option(string body)
{
_body = body;
_isCorrect = null;
}
public Option(string body, bool isCorrect)
{
_body = body;
_isCorrect = isCorrect;
}
#endregion
#region methods
public override string ToString()
{
return _body;
}
#endregion
}
and:
public class Question
{
private string _body;
private Option[] _optionsArray;
private List<Option> _optionsList;
#region properties
public string Body
{
get { return _body; }
}
public Option[] Options
{
get { return _optionsArray; }
}
public List<Option> OptionsList
{
get { return _optionsList; }
}
#endregion
#region constructors
public Question(string body, Option[] options)
{
_body = body;
_optionsArray = options;
_optionsList = new List<Option>();
foreach (Option opt in options)
{
_optionsList.Add(opt);
}
}
#endregion
#region methods
public override string ToString()
{
return _body;
}
public List<Option> GetOptions()
{
return OptionsList;
}
#endregion
}
My webform looks like this:
<div runat="server" ID="quizDiv">
<br />
<br />
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<%--<asp:Label ID="questionBody" runat="server" Text=<%# DataBinder.Eval(Container.DataItem, "Body") %>>--%>
<asp:Label ID="questionBody" runat="server" Text=<%# ((Question)Container.DataItem).Body %>>
<asp:radiobuttonlist ID="blah" runat="server" DataTextField="Body" DataValueField="Body" DataSource=<%# ((Question)Container.DataItem).OptionsList %> >
</asp:radiobuttonlist>
</asp:Label>
</ItemTemplate>
</asp:Repeater>
<br />
</div>
and the code-behind like so:
protected void btnStart_Click(object sender, EventArgs e)
{
Dataset1 ds = new Dataset1();
question = ds.CreateQuestion();
List<Question> qts = new List<Question>();
qts.Add(question);
Repeater1.DataSource = qts;
Repeater1.DataBind();
}
For the time being I am just using one question. The label displaying my question shows up fine, but no radio buttons show up for displaying the answer options. I have gone through many samples, and this seems to work for people when they use data from a DB via a DataTable or DataSet. However no matter how much I to play around with the Datasource, DataValueField and DataTextField parameters the RadioButtonList remains utterly barren. As you can see, I initially used an array of Option and also tried a List but to no avail.
What am I missing here?
EDIT - Found my mistake
I had the <asp:label> and <asp:radiobuttonlist> tags nested wrong! The label was encapsulating the radiobuttonlist and causing the problem from what I can make out.
ALTERNATIVE - thanks to balexandre
balexandre did provide a workable alternative by using only code-behing. Thank you!
I am including the code listing of this alternative for anyone who needs it and happens across this post.
Change the markup to look like this:
<asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Repeater1_ItemDataBound">
<ItemTemplate>
<%--<asp:Label ID="questionBody" runat="server" Text=<%# DataBinder.Eval(Container.DataItem, "Body") %>>--%>
<asp:Label ID="questionBody" runat="server" Text=<%# ((Question)Container.DataItem).Body %>>
</asp:Label>
<asp:radiobuttonlist ID="blah" runat="server" >
</asp:radiobuttonlist>
</ItemTemplate>
</asp:Repeater>
and the code-behind must have the event handler:
protected void Repeater1_ItemDataBound(Object Sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
RadioButtonList rbl = (RadioButtonList)e.Item.FindControl("blah");
// do anything with your rbl
foreach (Option opt in question.Options)
{
rbl.Items.Add(opt.ToString());
}
}
}
you can only access the template using the Repeater method OnItemDataBound witch is invoked before it draws anything to the page.
void Repeater1_ItemDataBound(Object Sender, RepeaterItemEventArgs e) {
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) {
RadioButtonList rbl = (RadioButtonList)e.Item.FindControl["blah"];
// do anything with your rbl
}
}
Or by looping through all the Controls in the Repeater Collection, witch for example you have submited the page.
BTW, and just for your information
this code:
private string _body;
private bool? _isCorrect;
public string Body
{
get { return _body; }
}
public bool? IsCorrect
{
get { return _isCorrect; }
}
is the same as
public string Body { private get; }
public bool? IsCorrect { private get; }