Social Icons

twitter google plus linkedin rss feed

Pages

2.2.12

Extending, Overriding and Base Classes

A couple of days ago my cousin asked me about the meaning of the word override. I tried to explain it with a couple of stupid examples and both sounded dull… Well this is a real life example.

We want to create Silverlight web parts and all of them share the same basic properties and the same render method. So extending Microsoft.SharePoint.WebPartPages.WebPart we will create a BaseSilverlightWebPart with this features (overriding the render method of the WebPart class) and then we will use it to create the other web parts easily.

The base class is like this:
    public abstract class BaseSilverlightWebpart : Microsoft.SharePoint.WebPartPages.WebPart
    {
        #region Web Part Properties
        [Personalizable(PersonalizationScope.Shared)]
        [WebBrowsable(true)]
        [System.ComponentModel.Category("Stratex")]
        [WebDisplayName("XAP List URL")]
        [Description("Select the URL of the XAP list.")]
        public string XAPListUrl { get; set; }
        #endregion

        #region Private Properties
        Dictionary<string, string> InitParams;
        #endregion

        #region Abstract
        /// <summary>
        /// Setup here the of the XAP you will use
        /// </summary>
        public abstract string XAPName { get; }

        /// <summary>
        /// Setup here the initial parameters you will use in your Silverlight Web Part
        /// </summary>
        public abstract void SetUpParameters();
        #endregion

        #region Methods
        public void AddParameter(string Name, string Value)
        {
            if (InitParams == null)
                InitParams = new Dictionary<string, string>();

            if (InitParams.ContainsKey(Name))
                InitParams[Name] = Value;
            else
                InitParams.Add(Name, Value);
        }
        #endregion

        #region Overrides
        protected override void CreateChildControls()
        {
            SetUpParameters();

            if (string.IsNullOrEmpty(XAPListUrl))
                XAPListUrl = string.Format("{0}/Lists/XAPLibrary/", SPContext.Current.Web.ServerRelativeUrl);

            //Sometimes when you create the web part it's 0px by 0px... ¬ ¬
            if (string.IsNullOrEmpty(Height)) Height = "150px";
            if (string.IsNullOrEmpty(Width)) Width = "150px";

            LiteralControl obj = new LiteralControl();
            obj.Text = "<object id='silverlightHost' height='" + Height + "' width='" + Width +
                @"' data='data:application/x-silverlight-2,' type='application/x-silverlight-2' style='display:block' class='ms-dlgDisable'>
                            <param name='Source' value='" + XAPListUrl + XAPName + @"' />
                            <param name='MinRuntimeVersion' value='3.0.40624.0' />
                            <param name='Background' value='#00FFFFFF' />
                            <param name='windowless' value='true' />
                            <param name='autoUpgrade' value='true' />
                            ";

            if (InitParams.Count > 0)
            {
                obj.Text +="<param name='initParams' value='";

                int i = 0;
                foreach (var param in InitParams)
                {
                    if (i++ == 0)
                        obj.Text += string.Format("{0}={1}", param.Key, param.Value);
                    else
                        obj.Text += string.Format(", {0}={1}", param.Key, param.Value);
                }

                obj.Text += @"' />
                ";
            }
            obj.Text += @"<a href='http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0' style='text-decoration: none;'>
                <img src='http://go.microsoft.com/fwlink/?LinkId=108181' alt='Click here to install Silverlight' style='border-style: none'/>
                </a>
                </object>";

            this.Controls.Add(obj);
        }
        #endregion
    }
Extending it we can create a Silverlight Web Part as easy as:
    public class DynamicStrategyMap : BaseSilverlightWebpart
    {
        #region Overrides
        public override string XAPName
        {
            get { return "StratexPointStrategyMap.xap"; }
        }

        public override void SetUpParameters()
        {
            AddParameter("site", HttpUtility.UrlEncode(SPContext.Current.Web.ServerRelativeUrl));
        }
        #endregion
    }
Note that wou dont have to override nothing if you don't need to. The render method is exactly the same as in the base class so we don't have to name it. The class will use its base class method automatically. Look how we are saving code not writing again all the properties or the big render method from the base class here, we just change what we really need to change.
We can also add new properties if we want as in:
    public class StratexHeartBeat : BaseSilverlightWebpart
    {
        #region WebPartProperties
        [Personalizable(PersonalizationScope.Shared)]
        [WebBrowsable(true)]
        [System.ComponentModel.Category("Stratex")]
        [WebDisplayName("NumberOfEvents")]
        public string NumberOfEvents { get; set; }

        [Personalizable(PersonalizationScope.Shared)]
        [WebBrowsable(true)]
        [System.ComponentModel.Category("Stratex")]
        [WebDisplayName("TimerLapse")]
        public string TimerLapse { get; set; }

        [Personalizable(PersonalizationScope.Shared)]
        [WebBrowsable(true)]
        [System.ComponentModel.Category("Stratex")]
        [WebDisplayName("Indicator Summary Url")]
        public string IndicatorSummaryUrl { get; set; }
        #endregion

        #region Overrides

        public override string XAPName
        {
            get { return "StratexHeartBeat.xap"; }
        }

        public override void SetUpParameters()
        {
            AddParameter("site", HttpUtility.UrlEncode(SPContext.Current.Web.Url));

            if (string.IsNullOrEmpty(IndicatorSummaryUrl))
                IndicatorSummaryUrl = string.Format("{0}/Lists/WebPartPages/IndicatorSummary.aspx", SPContext.Current.Web.ServerRelativeUrl);

            AddParameter("indicatorsummaryurl", IndicatorSummaryUrl);

            if (Common.ConvertToInt(NumberOfEvents) < 1) NumberOfEvents = "1";

            AddParameter("numberofnews", NumberOfEvents);

            if (Common.ConvertToInt(TimerLapse) < 1) TimerLapse = "1";

            AddParameter("timerlapse", TimerLapse);
        }
        #endregion
    }
Or we can ever add more code to the render overriding the overrided render method.
    public class Commentary : BaseSilverlightWebpart
    {
        #region Overrides
        public override string XAPName
        {
            get { return "Commentary.xap"; }
        }

        public override void SetUpParameters()
        {
            AddParameter("site", HttpUtility.UrlEncode(SPContext.Current.Web.ServerRelativeUrl));
        }

        protected override void CreateChildControls()
        {
            base.CreateChildControls();

            //We are using this code to be able to close the explorer window from Silverlight
            LiteralControl JavaScript = new LiteralControl();

            JavaScript.Text = @"<script type='text/javascript'>
                                function doCloseLocal() 
                                {
                                    var version = parseFloat(navigator.appVersion.split('MSIE')[1]);

                                    if (version >= 7) {window.open('', '_parent', ''); }

                                    else { window.opener = self;  }

                                    window.close();
                                }
                                </script>";
            this.Controls.Add(JavaScript);
        }

        #endregion
    }
Note that before adding the new control we call the base.Render so the web part is rendered in the page.
So this is how overriding looks like in real life. Now it make sense… or does it?