In this blog post we will sample a custom control which allows users to select files uploaded to images and documents module and send them as e-mail attachments. We will create a custom control and make it look similar to the built in Download List control. However this control will allow users to select content items and send them to provided e-mail. Bellow is a sample of how our control will look like.
Let us first start by creating the control template for our custom control. We will populate the items in a RadGrid for ASP.NET AJAX as this control allows us to handle multiple selected items out of the box. We will make the control display items in a fashion similar to the built in Download List control. We will also need to add a text box for inputting user e-mail, a couple of validators for validating correct e-mails and a button, which when clicked will send items to specified e-mail address. The sample control template can be found bellow:
<%@ Control Language="C#" %>
<%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>
<
telerik:RadGrid
ID
=
"ItemsGrid"
runat
=
"server"
AllowAutomaticInserts
=
"False"
AllowAutomaticUpdates
=
"False"
AllowAutomaticDeletes
=
"False"
ShowStatusBar
=
"True"
AllowPaging
=
"True"
PageSize
=
"50"
EnableViewState
=
"True"
Skin
=
"Sitefinity"
AllowMultiRowSelection
=
"True"
GridLines
=
"None"
AutoGenerateColumns
=
"False"
>
<
MasterTableView
AllowMultiColumnSorting
=
"false"
CommandItemDisplay
=
"None"
CssClass
=
"listItems listItemsBindOnClient"
Width
=
"98%"
>
<
Columns
>
<
telerik:GridClientSelectColumn
UniqueName
=
"CheckboxSelectColumn"
Text
=
"Select"
></
telerik:GridClientSelectColumn
>
<
telerik:GridBoundColumn
UniqueName
=
"ID"
DataField
=
"ID"
Visible
=
"false"
></
telerik:GridBoundColumn
>
<
telerik:GridTemplateColumn
UniqueName
=
"Name"
HeaderText
=
"Name"
>
<
ItemTemplate
>
<
asp:HyperLink
ID
=
"DownloadLink"
runat
=
"server"
>
<
asp:Literal
ID
=
"Name"
runat
=
"server"
></
asp:Literal
>
</
asp:HyperLink
>
</
ItemTemplate
>
</
telerik:GridTemplateColumn
>
<
telerik:GridTemplateColumn
UniqueName
=
"Extension"
HeaderText
=
"Extension"
>
<
ItemTemplate
>
<
asp:Literal
id
=
"Extension"
runat
=
"server"
></
asp:Literal
>
</
ItemTemplate
>
</
telerik:GridTemplateColumn
>
<
telerik:GridTemplateColumn
UniqueName
=
"Author"
HeaderText
=
"Author"
>
<
ItemTemplate
>
<
asp:Literal
id
=
"Author"
runat
=
"server"
></
asp:Literal
>
</
ItemTemplate
>
</
telerik:GridTemplateColumn
>
<
telerik:GridTemplateColumn
UniqueName
=
"UploadDate"
HeaderText
=
"Upload Date"
>
<
ItemTemplate
>
<
asp:Literal
id
=
"UploadDate"
runat
=
"server"
></
asp:Literal
>
</
ItemTemplate
>
</
telerik:GridTemplateColumn
>
<
telerik:GridTemplateColumn
UniqueName
=
"Size"
HeaderText
=
"Size"
>
<
ItemTemplate
>
<
asp:Literal
id
=
"Size"
runat
=
"server"
></
asp:Literal
>
</
ItemTemplate
>
</
telerik:GridTemplateColumn
>
<
telerik:GridTemplateColumn
UniqueName
=
"FileDownloadLink"
HeaderText
=
"Download Link"
>
<
ItemTemplate
>
<
asp:HyperLink
ID
=
"FileDownloadLink"
runat
=
"server"
Text
=
"Download Item"
></
asp:HyperLink
>
</
ItemTemplate
>
</
telerik:GridTemplateColumn
>
</
Columns
>
</
MasterTableView
>
<
ClientSettings
>
<
Selecting
AllowRowSelect
=
"true"
/>
</
ClientSettings
>
<
PagerStyle
Mode
=
"NumericPages"
/>
</
telerik:RadGrid
>
<
asp:Label
ID
=
"emailTxtLbl"
runat
=
"server"
AssociatedControlID
=
"emailTxt"
></
asp:Label
>
<
telerik:RadTextBox
ID
=
"emailTxt"
runat
=
"server"
Skin
=
"Sitefinity"
ValidationGroup
=
"sendemail"
></
telerik:RadTextBox
>
<%--Regular expression validator to ensure valid e-mail addresses are provided--%>
<
asp:RegularExpressionValidator
ID
=
"emailValidator"
runat
=
"server"
Display
=
"Dynamic"
ErrorMessage
=
"Please, enter valid e-mail address."
ValidationExpression
=
"^[\w\.\-]+@[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]{1,})*(\.[a-zA-Z]{2,3}){1,2}$"
ControlToValidate
=
"emailTxt"
ValidationGroup
=
"sendemail"
>
</
asp:RegularExpressionValidator
>
<%-- a validator to ensure e-mails are entered before the send button is clicked--%>
<
asp:RequiredFieldValidator
ID
=
"Requiredfieldvalidator1"
runat
=
"server"
Display
=
"Dynamic"
ControlToValidate
=
"emailTxt"
ErrorMessage
=
"Please, enter an e-mail!"
ValidationGroup
=
"sendemail"
/>
<
asp:LinkButton
ID
=
"SendBtn"
runat
=
"server"
Text
=
"Send Selected"
CausesValidation
=
"true"
ValidationGroup
=
"sendemail"
/>
After we have created the control template for our control it is time to start building it. The control will inherit from Simple control. It will also implement the IFilterableContentControl to allow us to use filter expressions and filter content which will populate the grid. First lets get a reference of the controls in the template:
protected
override
void
CreateChildControls()
{
if
(Page ==
null
|| DesignMode)
{
Label noDesignModeLabel =
new
Label();
noDesignModeLabel.Text =
"The Download List control cannot be rendered in Design Mode"
;
this
.Controls.Add(noDesignModeLabel);
}
else
{
base
.CreateChildControls();
libraryManager =
new
LibraryManager(ProviderName);
//subscribe to command event of the send button
SendButton.Command +=
new
CommandEventHandler(SendButton_Command);
//subscribe to the ItemDataound event handler of the RadGrid
ItemsGrid.ItemDataBound +=
new
GridItemEventHandler(ItemsGrid_ItemDataBound);
//check for filter expression
if
(FilterExpression !=
string
.Empty)
{
//if we have specified a filter expression we will get only content which matches our filter expression
ContentFilterBuilder filterBuilder =
new
ContentFilterBuilder(
this
);
if
(filterBuilder.IsFilterValid)
{
ItemsGrid.DataSource = libraryManager.GetContent(0, 0, filterBuilder.ParseMetaFieldsFilter(), filterBuilder.ParseParentsFilter());
}
}
else
{
//if there is no filter expression we will only get content from non image libraries
ItemsGrid.DataSource = libraryManager.GetContent(0,0,
"Name ASC"
,
this
.GetParentIds());
}
ItemsGrid.DataBind();
}
}
//gets IDs of libraries which are not Image type libraries
protected
Guid[] GetParentIds()
{
List<Guid> parentIDs =
new
List<Guid>();
foreach
(ILibrary library
in
libraryManager.GetAllLibraries(
"Image"
,
false
))
{
parentIDs.Add(library.ID);
}
return
parentIDs.ToArray();
}
As you can see from the inline comments above we need to subscribe to the ItemDataBound event of the grid control. In this event we will populate the meta data and download links for each item in the grid. Bellow is the code for this event handler:
void
ItemsGrid_ItemDataBound(
object
sender, GridItemEventArgs e)
{
if
(e.Item
is
GridDataItem)
{
IContent cnt = (IContent)e.Item.DataItem;
foreach
(var MetaKey
in
libraryManager.MetaKeys)
{
ITextControl textControl = (ITextControl)e.Item.FindControl(MetaKey.Key);
if
(textControl !=
null
)
{
textControl.Text = cnt.GetMetaData(MetaKey.Key).ToString();
if
(MetaKey.Key ==
"Size"
)
{
long
num;
long
.TryParse(textControl.Text,
out
num);
textControl.Text = LibraryHelper.FormatSizeString(num);
}
}
}
Literal UploadDate = (Literal)e.Item.FindControl(
"UploadDate"
);
HyperLink DownloadLink = (HyperLink)e.Item.FindControl(
"DownloadLink"
);
HyperLink FileDownloadLink = (HyperLink)e.Item.FindControl(
"FileDownloadLink"
);
if
(UploadDate !=
null
)
{
UploadDate.Text = cnt.DateCreated.ToShortDateString();
}
if
(DownloadLink !=
null
)
{
DownloadLink.NavigateUrl = cnt.UrlWithExtension;
}
if
(FileDownloadLink !=
null
)
{
FileDownloadLink.NavigateUrl = cnt.UrlWithExtension;
}
}
}
We also need to handle the click event of the send button. When this button is clicked we will get all selected items from the grid and add them as attachments to an e-mail message. You will need to have valid SMTP setting in order to make this work:
void
SendButton_Command(
object
sender, CommandEventArgs e)
{
GridItemCollection selectedItems = ItemsGrid.SelectedItems;
MailMessage newMesssage =
new
MailMessage();
//modify this to fit your requirements
newMesssage.From =
new
MailAddress(
"admin@mymail.com"
);
newMesssage.To.Add(
new
MailAddress(EmailText.Text));
string
message = String.Format(
"Message body"
);
foreach
(GridDataItem item
in
ItemsGrid.SelectedItems)
{
libraryManager =
new
LibraryManager();
TableCell id = item[
"ID"
];
IContent contentItem = libraryManager.GetContent(
new
Guid(id.Text));
string
name = contentItem.GetMetaData(
"Name"
).ToString();
MemoryStream stream =
new
MemoryStream((
byte
[])contentItem.Content);
Attachment attachment =
new
Attachment(stream, String.Concat(name, contentItem.GetMetaData(
"Extension"
).ToString()), contentItem.MimeType);
newMesssage.Attachments.Add(attachment);
}
SmtpClient smtpClient =
new
SmtpClient();
smtpClient.Send(newMesssage);
}
This is the basic functionality of the control, which needs to be implemented. The complete code for the control and markup for its template can be downloaded from this link: MyDownloadListSource