Social Icons

twitter google plus linkedin rss feed

Pages

3.12.10

Copying ListViewWebparts between sites with their own custom views

In a new example of what I call "Guerrilla Coding" I had a couple of hours to develop a little program to copy hundreds of webpart pages full of ListViewWebparts, each one with its own custom view. I don't know if you feel the same, but I start to tremble every time I have to touch anything related to the ListViewWebpart

The ListViewWebparts create in the parent list a hidden view when we customize their view. This means that if you want to copy the webparts to a new site you'll have to copy the views from the parent list to its destination equivalent, I don't think I'm explaining my point well... I'd better paste the code...

What I do in this code snippet is copying the webparts from every origin file to the destination one giving them a special treatment if they are LisvViewWebpart which is enough for the application I need.

private static void CopyWebParts(SPFile origFile, SPFile destFile)
        {
            SPLimitedWebPartManager origWpm = origFile.GetLimitedWebPartManager(PersonalizationScope.Shared);
            SPLimitedWebPartManager destWpm = destFile.GetLimitedWebPartManager(PersonalizationScope.Shared);

            DeleteWebparts(destWpm);

            foreach (Microsoft.SharePoint.WebPartPages.WebPart webpart in origWpm.WebParts)
            {
                Microsoft.SharePoint.WebPartPages.WebPart newWp;

                if (webpart is ListViewWebPart)
                    newWp = UpdateListViewWebPart(webpart as ListViewWebPart, origFile.GetWeb(), destFile.GetWeb());
                else
                    newWp = webpart;

                destWpm.AddWebPart(newWp, Common.ConvertToString(newWp.ZoneID), newWp.ZoneIndex);
            }

            try
            {
                destFile.Publish("Added Web Parts");
                destFile.Approve("Web Part additions approved");
            }
            catch { }
        }

        private static ListViewWebPart UpdateListViewWebPart(ListViewWebPart webpart, SPWeb origWeb, SPWeb destWeb)
        {
            ListViewWebPart newWebPart = webpart; //yeah I know.

            string oldListName = webpart.ListName;
            string oldViewGuid = webpart.ViewGuid;

            SPList OrigList = origWeb.Lists.GetList(new Guid(oldListName), true);
            
            SPList DestList = destWeb.Lists[OrigList.Title];

            SPView OrigView = OrigList.GetView(new Guid(oldViewGuid));
            SPView DestView = DestList.Views.Add(string.Empty, OrigView.ViewFields.ToStringCollection(), OrigView.Query,
                OrigView.RowLimit, OrigView.Paged, OrigView.DefaultView);
            DestView.Hidden = OrigView.Hidden;
            DestView.Scope = OrigView.Scope;
            DestView.ApplyStyle(destWeb.ViewStyles.StyleByID(Convert.ToInt32(OrigView.StyleID)));

            DestView.Update();

            newWebPart.ViewGuid = DestView.ID.ToString("B").ToUpper();
            newWebPart.ListName = destWeb.Lists[OrigList.Title].ID.ToString("B").ToUpper();


            return newWebPart;
        }
And against all odds it worked, I hope I don't have to deal with this webparts for a while.

22.11.10

Code Snippets in C# and Why my TwoWay Bindings are not working?

Well, regarding to the problem with the TwoWay binding, today I’ve learnt that they don’t work magically; each property should implement the Property Change Notification, the INotifyPropertyChanged. It’s not that complex, It takes a little more time to declare the property this way (by the way, you have it perfectly explained here) and this leads us to the Code Snippets thing.

Creating code snippets is one of those things I’ve left to learn later a lot of times… until today that I had to create an object with more than thirty properties launching the PropertyChanged event and I couldn’t delay it further.
To increase my productivity I have wasted a little of time and I have created a code snippet for the properties implementing the INotifyPropertyChanged. I’ve called it propNot I’m this creative, I can’t help it
To do so, in Visual Studio, I went to Tools and from there to Code Snippets Manager. There I chose C# and then I copied the address of the My Code Snippets folder.

I created a .snippet file on that folder with this content
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
 <CodeSnippet Format="1.0.0">
  <Header>
   <Title>propNot</Title>
   <Shortcut>propNot</Shortcut>
   <Description>Code snippet for properties with NotifyPropertyChanged</Description>
   <Author>Chan</Author>
   <SnippetTypes>
    <SnippetType>Expansion</SnippetType>
    <SnippetType>SurroundsWith</SnippetType>
   </SnippetTypes>
  </Header>
  <Snippet>
   <Declarations>
    <Literal>
     <ID>privName</ID>
     <Default>privName</Default>
     <ToolTip>Private name of the property</ToolTip>
    </Literal>
    <Literal>
     <ID>pubName</ID>
     <Default>pubName</Default>
     <ToolTip>Public name of the property</ToolTip>
    </Literal>
    <Literal>
     <ID>type</ID>
     <Default>string</Default>
     <ToolTip>Type of the property</ToolTip>
    </Literal>
   </Declarations>
   <Code Language="csharp"><![CDATA[private $type$ $privName$;
        
    public $type$ $pubName$
    {
     get { return $privName$; }

     set
     {
      $privName$ = value;
      // Call NotifyPropertyChanged when the property is updated
      NotifyPropertyChanged("$pubName$");
     }
    }]]>
   </Code>
  </Snippet>
 </CodeSnippet>
</CodeSnippets>
It’s tested and working, both the TwoWay binding and the Code Snippet.

Now that I know how to do them I think I’ll do them really usually. --EDIT-- I lied, I don't do them that usually because I am VERY lazy, but I do use this other snippet a lot:
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
 <CodeSnippet Format="1.0.0">
  <Header>
   <Title>INotify region with the necessary methods to implement the interface</Title>
   <Shortcut>inotifyregion</Shortcut>
   <Description>Creates region with the necessary methods to implement the interface INotifyPropertyChanged</Description>
   <Author>Jose Sanchez</Author>
   <SnippetTypes>
    <SnippetType>Expansion</SnippetType>
    <SnippetType>SurroundsWith</SnippetType>
   </SnippetTypes>
  </Header>
  <Snippet>
   <Declarations />
   <Code Language="csharp"><![CDATA[#region INotifyMethods
        // Declare the event
        public event PropertyChangedEventHandler PropertyChanged;

        // Create the OnPropertyChanged method to raise the event
        protected void NotifyPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
        #endregion]]>
   </Code>
  </Snippet>
 </CodeSnippet>
</CodeSnippets>

9.11.10

Changing the NewValue in the PropertyChangedCallback

I don't usually write about Silverlight, this is for two main reasons, first because there's a lot of information in a lot of blogs and second because I don't work that much with Silverlight so I don't find that much problems. It was perfect until I really knew it, same as many other things...


Lately I'm using a lot this technology so new to me and already outdated for Microsoft and doubts are arising i.e. the one in today's post.

I was creating a new button to add it to a DataGrid as a DataGridTemplateColumn and I needed to create a DependencyProperty to bind it, everything very straightforward so far, but in the last moment when I was seen myself victorious I found a problem. If the property (an URL in this case) is not valid, How can I change the NewValue in the PropertyChangedCallback?

The trick is to call SetValue, that doesn't trigger the event; otherwise we'll get an infinite loop. It'll be something like this:

public string CommentsURL
{
    get { return (string)GetValue(CommentsURLProperty); }
    set { SetValue(CommentsURLProperty, value); }
}

public static readonly DependencyProperty CommentsURLProperty =
    DependencyProperty.Register("CommentsURL", typeof(string), typeof(ButtonComments),
    new PropertyMetadata(new PropertyChangedCallback(ChangedURL)));

private static void ChangedURL(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    try
    {
        string url = e.NewValue.ToString().Split(',')[0];
        new Uri(url);
        d.SetValue(e.Property, url);

        (d as ButtonComments).IsEnabled = true;
    }
    catch
    {
        (d as ButtonComments).IsEnabled = false;
    }
}
Note the refinement of the code, always avoiding the exceptions before they occur.


In the end, if someone feels curious about the result, the wepbart ended like this:



"Intellectuals solve problems; geniuses prevent them."

26.10.10

SharePoint and New Relic's RPM

I have just installed, in one of my demo servers, a copy of New Relic's RPM just to see by myself how it works.

Unbelievably it has installed without issues and it has started to work not a very common thing in the world of SharePoint.

After installing it,the free version, of course, they upgraded my licence to a gold one for 8 days to give me time to test the product in all its plenitude so a couple of minutes after deploying in my server I had a whole lot of statistics and graphs showing me once more that my web services son lentos and the response times of MOSS just after it wakes up are not the best in the world.


I have really liked the charts about the system performance. Never before was so easy for an employee to prove the server slow and that it should be improved and where (SQL, RAM or CPU they forgot about the HD)


To whom may be still dubious about trying it I can tell that (in my environment) SharePoint, the web services, the reporting services and anything else is working perfectly, or at least as perfectly as it was before the installation I've just found an error in a report thanks to RPM, the perfect excuse to bother the BI guy

Well, as I am more into complaining than into praising I'll stop talking about this product.

In other time I've had huge public servers under my boot, but now I see myself clicking fast and repeatedly to fake server traffic...

The less hair, the less power, it has always been that way.

17.9.10

Lambdas, Method Extensions and RunWithElevatedPrivileges

Nowadays it's not a problem for anyone to create a new site as an administrator regardless of the loged user, but I'd like to suggest a function that seems useful to me:
/// 
        /// Returns a NEW site with full permissions
        /// 
        public static SPSite OpenSiteWithElevatedPrivileges(this SPSite site)
        {
            SPSite newSite = null;

            SPSecurity.RunWithElevatedPrivileges(() => newSite = new SPSite(site.ID));

            return newSite;
        }
Looks easy, doesn't it? I like doing
SPSite site = SPContext.Current.Site.OpenSiteWithElevatedPrivileges();
What do you think?

15.9.10

Microsoft Chart Controls and MOSS2007

I've known the existence of this controls for long, but I've never had the urge to use them. A couple of times I've needed a graph I've created it drawing dots in a bitmap (obviously the simpler way)
But now at Manigent we have to deliver a lot of complex charts... I thought I could use Excel Services but it does not make sense to export data from the sharepoint object model to an Excel book and create the graph from there so I decided it would be a good chance to learn how to use the .Net charting controls.

First of all I followed the steps on this blog to set up the development environment:
Of course I didn't read the instructions and I went straight to the creation of the webpart.
First thing I did was to add the reference to the System.Web.DataVisualization DLL which was installed in C:\Program Files\Microsoft Chart Controls\Assemblies\

That's enough for you to start creating the webpart with Visual Studio. The code I used for the webpart was an adaptation of an example from the documentation:
public class ControlAssessmentChart : Microsoft.SharePoint.WebPartPages.WebPart
    {
        Chart Chart1 = new Chart();

        protected override void CreateChildControls()
        {
            Chart1.Width = 400;
            Chart1.Height = 300;
            Chart1.RenderType = RenderType.ImageTag;

            Chart1.Palette = ChartColorPalette.BrightPastel;
            Title t = new Title("StratEx Testing Chart", Docking.Top,
                new System.Drawing.Font("Trebuchet MS", 14, System.Drawing.FontStyle.Bold)
                , System.Drawing.Color.FromArgb(26, 59, 105));
            Chart1.Titles.Add(t);
            Chart1.ChartAreas.Add("Test 1");

            // create a couple of Test
            Chart1.Series.Add("Test 1");
            Chart1.Series.Add("Test 2");

            //ChartType can also be added to the series
            // add points to Test 1
            Chart1.Series["Test 1"].Points.AddY(5);
            Chart1.Series["Test 1"].Points.AddY(8);
            Chart1.Series["Test 1"].Points.AddY(12);
            Chart1.Series["Test 1"].Points.AddY(6);
            Chart1.Series["Test 1"].Points.AddY(9);
            Chart1.Series["Test 1"].Points.AddY(4);

            // add points to Test 2
            Chart1.Series["Test 2"].Points.AddY(2);
            Chart1.Series["Test 2"].Points.AddY(6);
            Chart1.Series["Test 2"].Points.AddY(18);
            Chart1.Series["Test 2"].Points.AddY(16);
            Chart1.Series["Test 2"].Points.AddY(21);
            Chart1.Series["Test 2"].Points.AddY(14);

            Chart1.BorderSkin.SkinStyle = BorderSkinStyle.Emboss;
            Chart1.BorderColor = System.Drawing.Color.FromArgb(26, 59, 105);
            Chart1.BorderlineDashStyle = ChartDashStyle.Solid;
            Chart1.BorderWidth = 2;

            Chart1.Legends.Add("Legend1");

            Chart1.Legends["Legend1"].Enabled = true;

            Controls.Add(Chart1);
        }
    }
After deploying the webpart in sharepoint I tried to run it but I got the error:

[HttpException (0x80004005): Error executing child request for ChartImg.axd.]

To solve it I followed the tip at this forum and added the line:
<add path="ChartImg.axd" verb="GET,HEAD" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/>
To the web.config (inside <system.web><httpHandlers>)
After that I tried to run the webpart again but I got:

[DirectoryNotFoundException: Invalid temp directory in chart handler configuration [c:\TempImageFiles\].]

To solve this new issue I had to follow the instructions at this post and added:
<add key="ChartImageHandler" value="storage=file;timeout=20;" />
In the web.config inside <appSettings>

Finally it worked!.

RadarStackedBarStackedColumn
These charts belong to the same data set (is not the same in the code) but changing the ChartType parameter in the series.

It looks really powerful, let's see how it performs in production…

14.9.10

Developing is Painful in English Too

Why creating a second blog in English just to say the same stupid things that no one is interested in?

Easy:
  • First of all, because is free.
  • Second, because I have a small but growing number of English speaking friends that are just as crazy as I am and they could be interested.
  • Third, because is a good excuse to practice my English.
  • Fourth, because I want to compare the impact of the post in both languages.
  • Fifth, because I want to demonstrate that there’s no need of knowing English to write a blog in English.
  • And sixth, never write a pentalogue if you’re not a parapsychologist or R.A. Salvatore.
For those of you that don’t know my other blog, I base my posts in the certainty that no knowledge is trivial, this allow me to write about really trivial topics that real developers already know, but in the other hand have proven to be really useful to me, because I tend to forget easily. Yes, this blog is a temple of selfishness.


I really hope this blog is of any use to anyone…

Welcome to Developing is Painful in English Too