Snippets from my blog where I tried to be a cool code blogger and failed miserably! (Ain't nobody got time for that)
Photo credits to Alexander Sollie
Recently, I created a small hack to use the awesome Font Awesome library alongside Ext JS (3.4).
This allows Font Awesome icons to be served as good as the Ext JS icons for Tree Panels.
The code sequences the function that removes x-tree-node-icon
during the render
event and adds the Font Awesome icons.
Here is the code –
// Add sequence to the render event to replace .x-tree-node-icon
Ext.sequence(Ext.tree.TreeNode.prototype, 'render', function (treenode) {
$('.x-tree-node-icon').removeClass('x-tree-node-icon').replaceWith(function () {
if (typeof($(this).attr('class')) != 'undefined')
return '<i class="' + $(this).attr('class') + '"/>';
else
$(this).addClass('.x-tree-node-icon');
});
});
// Intercept setIconCls so font awesome icons can be set by setIconCls method too
Ext.intercept(Ext.tree.TreeNode.prototype, 'setIconCls', function (cls) {
$($(this)[0].ui.elNode).find('i').removeClass().addClass(cls);
});
With this code hack, you can set Font Awesome icons like this from Ext Designer. Here is a screenshot -
If you're a rookie out there trying to dig your way through Sharepoint Web Services, here is some simple code to manage documents.
To manage documents, you will have to do the following -
Have a DTO (a Data Transfer Object – if necessary) to send the document information (if you are doing AJAX using jQuery or something)
public class DocLibDTO
{
public string Id { get; set; } // ID of the document
public string Index { get; set; } // Index of the document
public string FileName { get; set; } // File Name
public string FileTypeIcon { get; set; } // File Type Icon
public string CreatedOn { get; set; } // Created On
public string FileRef { get; set; } // Sharepoint File Reference
}
Before you upload the file, make sure the file doesn't exist in the document library.
/// <summary></pre>
/// Check if a file / folder exists
/// </summary>
/// <param name="FilePath">File Path</param>
/// <returns>Boolean whether file exists or not</returns>
public bool CheckFileExists(string FilePath)
{
Lists lists = new Lists();
lists.Url = "https://yoursharepointsite.com/_vti_bin/lists.asmx";
// Your Sharepoint credentials
lists.Credentials = new System.Net.NetworkCredential("Username", "Password");
XmlNode nodes;
System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
System.Xml.XmlElement query = xmlDoc.CreateElement("Query");
System.Xml.XmlElement viewFields = xmlDoc.CreateElement("ViewFields");
System.Xml.XmlElement queryOptions = xmlDoc.CreateElement("QueryOptions");
// Look for files whose ID is greater than 0
query.InnerXml = "<Where><Gt><FieldRef Name=\"ID\" />" +
"<Value Type=\"Counter\">0</Value></Gt></Where>";
viewFields.InnerXml = "<FieldRef Name=\"Title\" /><FieldRef Name=\"Description\" />";
queryOptions.InnerXml = "<ViewAttributes Scope=\"RecursiveAll\"/>";
// Get List Items from the Sharepoint List Library "UploadList"
nodes = lists.GetListItems("UploadList", null, query, viewFields, "5", queryOptions, null);
foreach (System.Xml.XmlNode node in nodes)
{
if (node.Name == "rs:data")
{
int index = 1;
for (int i = 0; i < node.ChildNodes.Count; i++)
{
if (node.ChildNodes[i].Name == "z:row")
{
if (node.ChildNodes[i].Attributes["ows_FileRef"].Value.Split('#')[1] == FilePath)
{
return true;
}
}
}
}
}
return false;
}
Depending on what you want to do - if you'd like to create a folder to upload documents, you can use this function. Totally optional!
/// <summary>
/// Creates Folder Method
/// </summary>
/// <param name="FolderPath">Folder Path</param>
/// <returns>Boolean whether success or failure</returns>
public bool CreateFolder(string FolderPath)
{
Dws dws = new Dws();
dws.Url = "https://yoursharepointsite.com/_vti_bin/dws.asmx";
dws.Credentials = new System.Net.NetworkCredential("Username", "Password");
if (!CheckFileExists(FolderPath))
{
dws.CreateFolder(FolderPath);
return true;
}
else
{
return false;
}
}
Now to the main part - Uploading a file.
/// <summary>
/// Upload File Method
/// </summary>
/// <param name="FormCollection">Form Collection from a POST Request</param>
/// <returns>JsonResult with success & msg</returns>
[AcceptVerbs(HttpVerbs.Post)]
public JsonResult UploadFile(FormCollection)
{
bool success = false;
string msg = "";
if(Request.Files.Count > 0)
{
for(int i = 0; i < Request.Files.Count; i++)
{
HttpPostedFileBase postedFile = Request.Files[i];
string fileExt = Path.GetExtension(postedFile.FileName).ToLower();
string fileName = Path.GetExtension(postedFile.FileName);
// With fileExt, you can make sure if you'd like the user to upload that type of file
byte[] postedFileBytes = new byte[postedFile.InputStream.Length];
postedFile.InputStream.Read(postedFileBytes, 0, (int)postedFile.InputStream.Length);
bool CanCreateFile = false;
Copy copy = new Copy();
copy.Url = "https://yoursharepointsite.com/_vti_bin/copy.asmx";
copy.Credentials = new System.Net.NetworkCredential("Username", "Password");
// This if condition is optional - Use if if you want to create a parent folder
if (!CheckFileExists("YourUploadList" + "/" + "AnyParentFolder"))
CanCreateFile = CreateFolder("YourUploadList" + "/" + "AnyParentFolder");
else
CanCreateFile = true;
// Upload the file, if everything looks good aka CanCreateFile
if (CanCreateFile)
{
string[] destinationUrl = { "https://yoursharepointsite.com/list/parentfolder/subfolder/" + fileName };
FieldInformation titleInfo = new FieldInformation
{
DisplayName = fileName,
InternalName = fileName,
Type = FieldType.Text,
Value = fileName
};
FileInfo file = new FileInfo(fileName);
string sourceUrl = file.FullName;
FieldInformation[] metaData = { titleInfo };
CopyResult[] result;
uint op = copy.CopyIntoItems(sourceUrl, destinationUrl, metaData, postedFileBytes, out result);
// Upload was successful
if(op == 0)
{
success = true;
msg = "Upload successful!"
}
// There was an error
else
{
success = false;
msg = "Couldn't upload file!"
break;
}
}
// Couldn't create folder - Optional
else
{
success = false;
msg = "Couldn't upload file!"
break;
}
}
return Json(new { success = success, msg = msg });
}
else
{
return Json(new { success = false, msg = "No files found!" });
}
}
Isolated Storage is nothing but a storage location in a user’s local filesystem where applications can store data.
It is generally exploited by web applications to store information of any kind (application data, user data, session state etc).
The initial quota for a Isolated Storage is 1MB, which could be modified later using code.
The Isolated Storage data in Windows is usually located here -
C:\Users\<User Profile>\AppData\Local\IsolatedStorage
Here is a simple code to show how Isolated Storage can be exploited -
using System.IO.IsolatedStorage;
private void SaveUserData(string UserName, string Pwd, int UserNumber)
{
var file = new XDocument(
new XElement("UserNum", UserNumber,
new XElement("UserName", UserName),
new XElement("Password", Pwd))
);
using(IsolatedStorageFile isf = new IsolatedStorageFile.GetUserStoreForApplication())
{
IsolatedStorageFileStream isfs=new IsolatedStorageFileStream("File1", FileMode.Append, isf);
file.Save(isfs);
}
}
In the above code, the GetUserStoreForApplication()
method gets the next available storage location available for the application.
In order to store data for the entire site, use GetUserStoreForSite()
.
You can increase the Isolated Storage space by doing something like the following -
int a = 2048000;
// This will increase the space to 2MB
isf.IncreaseQuotaTo(a);
Silverlight typically uses Isolated Storage. To view quotas of different Silverlight applications
Right click the Silverlight Application > Select Silverlight > Application Storage
You'd see something like this -
Data Binding in Silverlight is pretty cool. You can basically bind a UserControl
to a collection of data.
A good example for data binding would be - Imagine a tree of depth say 1000. Instead of adding 1000 TreeViewItems
manually, you can write a few lines of code to bind your TreeView
to a Collection
.
Here is a basic example to bind a TreeView
to a data source. For a nested binding (a node within a node), a DataTemplate
uses another DataTemplate
as it's ItemTemplate
.
It's best practice to add the Template (DataTemplate
or HierarchicalDataTemplate
) to any UserControl’s Resource which is at a higher level and at a scope of visibility to the desired control. This facilitates code re-usability by the child controls.
As an example I created this sample application, where a HierarchicalDataTemplate
uses another HierarchicalDataTemplate
as ItemTemplate
.
The simplest example I could think of was a collection of Files and Folders.
Though the idea was something like an File Explorer. I used a simple File and Folder collection just to show how nested binding works.
To make the application look like a File Explorer, I created a Grid with two columns containing a TreeView
on the left pane and a ListBox
on the right pane.
Having created controls which can contain Items, I create two HierarchicalDataTemplates
- one for files and the other for the folders. To keep it simple, I use a StackPanel
which holds an Image
and a TextBlock
which has the File / Folder’s name as its Text.
Something like this -
<common:HierarchicalDataTemplate x:Name="template2">
<StackPanel Orientation="Horizontal">
<Image x:Name="imgTemplate2" Source="Images/file-icon.png" Height="15" Width="15"></Image>
<TextBlock x:Name="txtTemplate2" Text="{Binding FileName}"></TextBlock>
</StackPanel>
</common:HierarchicalDataTemplate>
<common:HierarchicalDataTemplate x:Name="template1" ItemTemplate="{StaticResource template2}"
ItemsSource="{Binding Files}">
<StackPanel Orientation="Horizontal">
<Image x:Name="imgTemplate1" Source="Images/Open-Folder-icon.png" Height="15" Width="15"></Image>
<TextBlock x:Name="txtTemplate1" Text="{Binding FolderName}"></TextBlock>
</StackPanel>
</common:HierarchicalDataTemplate>
Having created the HierarchicalDataTemplates for the Files and Folders which can be used as ItemsSource
for TreeView
, create a HierarchicalDataTemplate
for the ListBox
.
<common:HierarchicalDataTemplate x:Name="template3">
<StackPanel Orientation="Horizontal">
<Image x:Name="imgTemplate3" Source="Images/file-icon.png" Height="25" Width="25"></Image>
<TextBlock x:Name="txtTemplate3" Text="{Binding FileName}"></TextBlock>
</StackPanel>
</common:HierarchicalDataTemplate>
After creating all the HierarchicalDataTemplates, create the TreeView
and ListBox
and bind them to their respective HierarchicalDataTemplates
<controls:TreeView x:Name="TreeBind" ItemTemplate="{StaticResource template1}" ItemsSource="{Binding Folders}"
SelectedItemChanged="TreeBind_SelectedItemChanged">
</controls:TreeView>
<ListBox x:Name="lstRight" Grid.Column="1" ItemTemplate="{StaticResource template3}" ItemsSource="{Binding Folders}"
SelectionChanged="lstRight_SelectionChanged">
</ListBox>
Create a class for FileInfo
and FolderInfo
and to populate the TreeView
// Class for FileInfo
public class FileInfo
{
private string _fileName;
public string FileName
{
get { return _fileName; }
set
{
if (_fileName != value)
_fileName = value;
}
}
}
// Class for FolderInfo
public class FolderInfo
{
private string _folderName;
public string FolderName
{
get { return _folderName; }
set
{
if (_folderName != value)
_folderName = value;
}
}
public ObservableCollection<FileInfo> Files { get; set; }
}
// Method to populate TreeView
private void PopulateTreeView()
{
for (int i = 0; i < 10; i++)
files.Add(new FileInfo() { FileName = "File" + i });
for (int i = 0; i < 10; i++)
{
Folders.Add(new FolderInfo()
{
FolderName = "Folder" + i,
Files = files
});
}
TreeBind.ItemsSource = Folders;
}
To make the application look like a File Explorer, create a SelectedItemChanged
event for the TreeView
and ListBox
.
/// <summary>
/// LstRight SelectionChanged Event
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void lstRight_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
FileInfo file = (FileInfo)lstRight.SelectedItem;
MessageBox.Show("You selected " + file.FileName, "Sample MessageBox", MessageBoxButton.OK);
}
/// <summary>
/// TreeBind SelectedItemChanged Event
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void TreeBind_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
Type tSelectedItem = TreeBind.SelectedItem.GetType();
Type tFolders = typeof(FolderInfo);
Type tFiles = typeof(FileInfo);
if (tSelectedItem == tFolders)
{
FolderInfo folder = (FolderInfo)TreeBind.SelectedItem;
lstRight.ItemsSource = folder.Files;
}
if (tSelectedItem == tFiles)
{
FileInfo file = (FileInfo) TreeBind.SelectedItem;
MessageBox.Show("You selected " + file.FileName,"Sample MessageBox",MessageBoxButton.OK);
}
}
I recently created a Silverlight application that consumes WCF services. You can get the Silverlight SDK here.
Also, get the Silverlight Web Platform installer
and the Silverlight toolkit in case you haven’t done this previously.
I installed Silverlight 3 November 2009 tools for VS 2008 and think it's pretty stable.
In case you find debugging errors saying you will need Silverlight Managed debugging package (I mean after installing the toolkit and the web platform installer).
Something like this.
silverlight_chainer.exe /x:SLChainer \Folder
<currentDirectory>\SLChainer\Folder
location.
MainPage.xaml
. Create a TextBlock
and a Button
inside a StackPanel
,
which would look something like the following -
<UserControl x:Class="WCFIntroduction.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
<Grid x:Name="LayoutRoot">
<Grid.Background>
<LinearGradientBrush>
<GradientStop Color="Azure" Offset="0.5" />
<GradientStop Color="White" Offset="0.2" />
</LinearGradientBrush>
</Grid.Background>
<StackPanel x:Name="StackPanel">
<TextBlock x:Name="txtblock" Text="Text" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Button Content="Click Me!" Click="btn1_Click"></Button>
</StackPanel>
</Grid>
</UserControl>
Now add the WCF service to the ASP.NET web site by Right Click on project > Add > Add New Item > Silverlight Enabled WCF Service
.
Here is how the WCF Service looks -
using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Collections.Generic;
using System.Text;
namespace WCFIntroduction.Web
{
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class WCFService
{
[OperationContract]
public string PrintTime(string txt)
{
return string.Format("The Time now is: {0}", DateTime.Now);
}
// Add more operations here and mark them with [OperationContract]
}
}
This code returns a string with a Time Stamp on it. Having created the Service, Build the solution and check for errors. When the service is error-free, right click the service and select View in Browser.
This is essential because, if you miss this step, the port for the service will not be opened and you will encounter errors while adding the service to the Silverlight Application.
If your service is good, it should look something like this when you view it in a browser.
Add Service Reference
.
You should see the following dialog box -
Discover
button to discover the services inside the Solution.
MainPage.xaml.cs
code, and write the code to wire up the Service to the SL Application.
The basic steps to add a service to any project are -
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using WCFIntroduction.ServiceReference1;
namespace WCFIntroduction
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void btn1_Click(object sender, EventArgs e)
{
WCFServiceClient client = new WCFServiceClient();
client.PrintTimeCompleted+=new EventHandler<PrintTimeCompletedEventArgs>(client_PrintTimeCompleted);
client.PrintTimeAsync(txtblock.Text);
}
private void client_PrintTimeCompleted(object sender, PrintTimeCompletedEventArgs e)
{
txtblock.Text = e.Result;
}
}
}
This basically prints something like this when you click the button -