Karine Bosch’s Blog

On SharePoint

Silverlight control not stretching to its full width when hosted in a SharePoint Web Part


In the past few months I had a number of comments on my Silverlight posts where people ask how to make a Silverlight application stretch to the full width and/or height of the SharePoint web part that hosts the Silverlight application. I found a solution to this problem when working on Silverlight integration in SharePoint 2010, but I’m pretty certain this also works for SharePoint 2007.

Creating the Silverlight application

When you create the Silverlight application, you have to remove a Width and/or Height setting of the <UserControl>. Also don’t specify any width and/or hight on the container Grid or Canvas.

<UserControl x:Class="SLMarquee.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">
    <Canvas x:Name="LayoutRoot" >
        <Canvas.Background>
            <LinearGradientBrush StartPoint="0,0" EndPoint="1,1" >
                <GradientStop Color="Orange"/>
                <GradientStop Color="DarkRed" Offset="1"/>
            </LinearGradientBrush>
        </Canvas.Background>
        <TextBlock x:Name="MarqueeTextBox" Foreground="White" FontFamily="Comic Sans MS" FontSize="16" FontStyle="Italic"                   
                   Width="Auto" Height="Auto"  HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Padding="5"
                   Text="This is a very long text that will be stretched automatically when the width of the containing web part changes."/>
    </Canvas>
</UserControl>

I added LinearGradientBrush to the background of the Canvas to make it easier to demonstrate that the canvas stretches to the size of the web part.

Creating the SharePoint web part

The Silverlight application will be hosted in a <div> element. This <div> element is typically created in the CreateChildControls method of the web part. I created a classic web part in Visual Studio 2010 to let people working on SharePoint 2007 also benifit from the post.

    public class SilverlightWrapperWebPart : WebPart
    {
        protected override void CreateChildControls()
        {
            HtmlGenericControl div = new HtmlGenericControl("div");
            div.ID = "SilverlightHost";
            // generate the Silverlight control
            StringBuilder sb = new StringBuilder("<object id=\"SilverlightHost\"");
            sb.Append(" width=\"100%\"");
            sb.Append(" height=\"100%\"");
            sb.Append(" data=\"data:application/x-silverlight-2,\"");
            sb.Append(" type=\"application/x-silverlight-2\" >");
            sb.Append(" <param name=\"source\" value=\"/XAPS/SLMarquee.xap\"/>");
            sb.Append(" <a href=\"http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50401.0\" ");
            sb.Append(" style=\"text-decoration: none;\">");
            sb.Append(" <img src=\"http://go.microsoft.com/fwlink/?LinkId=108181\" ");
            sb.Append(" alt=\"Get Microsoft Silverlight\" ");
            sb.Append(" style=\"border-style: none\"/>");
            sb.Append(" </a>");
            sb.Append("</object>");
            div.InnerHtml = sb.ToString();
            this.Controls.Add(div);
        }
    }

If you want your Silverlight application stretch to the width and height of your web part, you have to set the width and height properties of the <object> tag to 100%. You can also choose that only the width needs to resize whenever the web part is resized. In that case you can specify an absolute value for the height and a relative value (in percentage) for the width. Notice also that no <param name=”width” value =”xxx” /> and no <param name=”height” value = “xxx” /> is specified within the <object></object> tags. This is also not necessary if you want your Silverlight application to stretch.

If I now add my web part to a web part page and set the width of the web part to 250 pixels and the height to 100 pixels (by using the standard tool pane of the web part), my Silverlight applications shows as follows:

If I modify the width of the web part to 750 pixels, I see the following:

Notice that not only the full text is now shown, but also that the background gradient is more stretched, proving that the canvas really resizes when the size of the web part is changed.

It is a different story if you want to wrap the text through the canvas because then the TextBox control need to have a fixed width, but that’s for tomorrow 🙂

July 24, 2010 - Posted by | SharePoint 2007, SharePoint 2010, Silverlight

5 Comments »

  1. Hi Karine,

    Nice Post!
    I have facing an issue about auto height, width for property. I have created the webpart hosting silverlight in it same as specified in post and passing the height, width to it using WebPart height, width however when I set the WebPart height, width property to “No. Adject to Zone”, webpart didn’t display anything means it did not set his height, width to accomodate silverlight in it.

    Can you please help me with this.

    Comment by Vishal | February 3, 2011 | Reply

  2. Hi Karine,

    Thanks for reply, here is my code, I have copied whole class.

    public abstract class SilverlightWebPart : System.Web.UI.WebControls.WebParts.WebPart
    {
    const string XapLocation = “/_layouts/mw/”;
    const string AssemblyName = “WebParts”;
    const string MinimumRuntimeVersion = “4.0.50826.0”;
    ///
    /// Gets a value indicating whether configuration properties can be initialized.
    ///
    ///
    /// true if can be properties initialized; otherwise, false.
    ///
    protected abstract bool PropertiesInitialized { get; }

    ///
    /// Gets the xap filename.
    ///
    /// The xap filename.
    protected abstract string XapFilename { get; }

    private static object _reflectionLock = new object();
    private static DomainAssemblyInfo.DomainAssemblyInfoDictionary _assemblyInfoItems;

    private static DomainAssemblyInfo.DomainAssemblyInfoDictionary AssemblyInfoItems
    {
    get
    {
    if (_assemblyInfoItems == null)
    {
    lock (_reflectionLock)
    {
    if (_assemblyInfoItems == null)
    {
    DomainAssemblyInfo asmInfo = new DomainAssemblyInfo();
    asmInfo.AssembliesToFind.Add(AssemblyName);

    _assemblyInfoItems = asmInfo.SearchAssemblyInfo();
    }
    }
    }
    return _assemblyInfoItems;
    }
    }

    protected override void RenderContents(HtmlTextWriter writer)
    {
    try
    {
    if (!PropertiesInitialized)
    {
    writer.WriteBeginTag(“div”);
    writer.Write(HtmlTextWriter.TagRightChar);
    writer.Write(“Set configuration properties to display web part.”);
    writer.WriteEndTag(“div”);
    return;
    }
    }
    catch (Exception ex)
    {
    writer.WriteBeginTag(“div”);
    writer.Write(HtmlTextWriter.TagRightChar);
    writer.Write(ex.Message);
    writer.WriteEndTag(“div”);
    return;
    }

    string parameters;

    try
    {
    parameters = String.Format(“webPartId=WebPart{0},width={1},height={2},{3}”, ClientID, Width, Height, GetParameterizedList());
    }
    catch (Exception e)
    {
    writer.WriteBeginTag(“div”);
    writer.Write(HtmlTextWriter.TagRightChar);
    writer.Write(String.Format(“Error: {0}”, e.Message));
    writer.WriteEndTag(“div”);
    return;
    }

    writer.WriteBeginTag(“style”);
    writer.WriteAttribute(“type”, “text/css”);
    writer.Write(HtmlTextWriter.TagRightChar);
    writer.Write(“.ms-WPBody div { overflow:hidden !important; }”);
    writer.WriteEndTag(“style”);

    writer.WriteBeginTag(“div”);
    writer.WriteAttribute(“id”, “silverlightControlHost”);
    writer.Write(HtmlTextWriter.TagRightChar);
    writer.WriteBeginTag(“object”);
    writer.WriteAttribute(“data”, “data:application/x-silverlight-2,”);
    writer.WriteAttribute(“type”, “application/x-silverlight-2”);
    writer.WriteAttribute(“width”, Width.ToString());
    writer.WriteAttribute(“height”, Height.ToString());
    writer.Write(HtmlTextWriter.TagRightChar);
    writer.WriteBeginTag(“param”);
    writer.WriteAttribute(“name”, “source”);
    string version;

    if (AssemblyInfoItems.ContainsKey(AssemblyName) && !String.IsNullOrEmpty(AssemblyInfoItems[AssemblyName].AssemblyItemFileVersion.Comments))
    version = HttpUtility.UrlEncode(AssemblyInfoItems[AssemblyName].AssemblyItemFileVersion.Comments);
    else
    version = DateTime.Now.ToString(“yyyyMMddHHmm”);

    writer.WriteAttribute(“value”, String.Format(“{0}{1}?v={2}”, XapLocation, XapFilename, version));
    writer.Write(” /”);
    writer.Write(HtmlTextWriter.TagRightChar);
    writer.WriteBeginTag(“param”);
    writer.WriteAttribute(“name”, “minRuntimeVersion”);
    writer.WriteAttribute(“value”, MinimumRuntimeVersion);
    writer.Write(” /”);
    writer.Write(HtmlTextWriter.TagRightChar);
    writer.WriteBeginTag(“param”);
    writer.WriteAttribute(“name”, “autoUpgrade”);
    writer.WriteAttribute(“value”, “true”);
    writer.Write(” /”);
    writer.Write(HtmlTextWriter.TagRightChar);
    writer.WriteBeginTag(“param”);
    writer.WriteAttribute(“name”, “initParams”);
    writer.WriteAttribute(“value”, parameters);
    writer.Write(” /”);
    writer.Write(HtmlTextWriter.TagRightChar);
    writer.WriteBeginTag(“a”);
    writer.WriteAttribute(“href”, “http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0”);
    writer.WriteAttribute(“style”, “text-decoration:none”);
    writer.Write(HtmlTextWriter.TagRightChar);
    writer.WriteBeginTag(“img”);
    writer.WriteAttribute(“src”, “http://go.microsoft.com/fwlink/?LinkId=108181”);
    writer.WriteAttribute(“alt”, “Get Microsoft Silverlight”);
    writer.WriteAttribute(“style”, “border-style:none”);
    writer.Write(” /”);
    writer.Write(HtmlTextWriter.TagRightChar);
    writer.WriteEndTag(“a”);
    writer.WriteEndTag(“object”);
    writer.WriteBeginTag(“iframe”);
    writer.WriteAttribute(“id”, “_sl_historyFrame”);
    writer.WriteAttribute(“style”, “visibility:hidden;height:0px;width:0px;border:0px”);
    writer.Write(HtmlTextWriter.TagRightChar);
    writer.WriteEndTag(“iframe”);
    writer.WriteEndTag(“div”);
    }

    private bool TryGetFieldInternalName(string webUrl, string listName, ref string fieldName, out Exception exception)
    {
    bool success = false;
    exception = null;

    using (SPWeb web = SPContext.Current.Site.OpenWeb(webUrl))
    {
    try
    {
    SPList list = web.Lists[listName];

    try
    {
    SPField field = list.Fields.GetField(fieldName);
    fieldName = field.InternalName;
    success = true;
    }
    catch (Exception) // Do nothing with this exception.
    {
    exception = new Exception(string.Format(“The field {0} was not found.“, fieldName));
    }
    }
    catch (Exception ex)
    {
    StringBuilder errorString = new StringBuilder(ex.Message);
    errorString.AppendLine(string.Format(“An error occured finding the specified list name. {0}“, listName));
    exception = new Exception(errorString.ToString());
    }
    }

    return success;
    }

    protected string GetInternalListFieldName(WebDisplayNameAttribute webpartPropertyDisplayName, string field, string primaryWebUrl, string primaryListName, string secondaryWebUrl, string secondaryWebListName)
    {
    try
    {
    Exception possibleException;
    if (string.IsNullOrEmpty(secondaryWebUrl) && string.IsNullOrEmpty(secondaryWebListName))
    {
    // First try the simple route since we don’t have a secondary list name / url provided
    if (TryGetFieldInternalName(primaryWebUrl, primaryListName, ref field, out possibleException))
    {
    return field;
    }
    else
    {
    if (possibleException != null)
    {
    throw possibleException;
    }
    }
    }
    else
    {
    if (field.Contains(“.”)) // Attempt to find the field using ‘dot’ notation. ListName.FieldName
    {
    int dotLocation = field.IndexOf(“.”);

    string dotlistName = field.Remove(dotLocation);
    field = field.Substring(dotLocation + 1);

    if (dotlistName == primaryListName)
    {
    if (TryGetFieldInternalName(primaryWebUrl, primaryListName, ref field, out possibleException))
    return string.Format(“{0}.{1}”, primaryListName, field);
    else
    if (possibleException != null)
    throw possibleException;
    }
    else if (dotlistName == secondaryWebListName)
    {
    if (TryGetFieldInternalName(secondaryWebUrl, secondaryWebListName, ref field, out possibleException))
    return string.Format(“{0}.{1}”, secondaryWebListName, field);
    else
    if (possibleException != null)
    throw possibleException;
    }
    else
    {
    throw new Exception(string.Format(“An error occured finding the list named \”{0}\” in the \”{1}\” webpart property with the configured values in the \”List Title\” or \”2nd List Title\” webpart properties.“, dotlistName, webpartPropertyDisplayName.DisplayName));
    }
    }
    else
    {
    throw new Exception(string.Format(“A secondary list name was specified.Please configure the \”{0}\” webpart property using the ListName.Field format.“, webpartPropertyDisplayName.DisplayName));
    }
    }
    }
    catch (Exception ex)
    {
    throw new Exception(ex.Message);
    }

    return field;
    }

    #region GetParameterizedList
    ///
    /// Gets the parameterized list from properties decorated with InitializationParameterNameAttribute.
    ///
    ///
    private string GetParameterizedList()
    {
    StringBuilder parameterizedList = new StringBuilder();

    PropertyInfo[] properties = this.GetType().GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
    if (properties.Length > 0)
    {
    for (int idx = 0; idx 0 && idx 0 && (itemArray.Length – 1) > 0)
    internalNameBuilder.Append(“;”);

    string name = item.Trim();

    if (!string.IsNullOrEmpty(name))
    internalNameBuilder.Append(GetInternalListFieldName(displayNameAttribute, name, webUrl, listName, secondaryWebUrl, secondaryListName));
    else
    internalNameBuilder.Append(string.Empty);
    }

    parameterizedList.Append(internalNameBuilder.ToString());
    }
    break;
    }
    }
    }
    }

    return parameterizedList.ToString();
    }
    #endregion
    }
    }

    Comment by Vishal | February 3, 2011 | Reply

  3. Additionally, I am trying to get avilable WebPart zone height, width from sharepoint however sharepoint didn’t expose any property for that.

    Comment by Vishal | February 3, 2011 | Reply

  4. Hi Karine,

    When we set the webpart height, width property to “No. Adjust width to fit zone”, webpart return its height, width as blank.

    How we can get the actual height, width of the webpart?

    Thanks,
    Vishal.

    Comment by Vishal Gurav | February 4, 2011 | Reply

  5. Hi Vishal,
    I explained in my post https://karinebosch.wordpress.com/2010/07/25/silverlight-control-not-stretching-to-its-full-width-when-hosted-in-a-sharepoint-web-part-continued/, that in the case you mention, the web part width has value NaN. Can the workaround in that post help you solve your problem?
    Karine

    Comment by Karine Bosch | February 5, 2011 | Reply


Leave a comment