Peter Walke

in
Extending the K2 Black Pearl TaskList Webpart – Show or Hide Visibility based upon SharePoint group membership

The Black Pearl TaskList web part is a web part that can get users up and running quickly to view what outstanding tasks on his or her plate.  If you need to extend it, it might not be readily apparent how to do it.      I needed to extend the Webpart to either show or hide itself based upon whether a user belonged to a specific group. 

Step 1:  Finding the TaskList dll

I did some digging in SharePoint designer and found the .webpart file for the web part.  It lives at catalogs/wp/K2TaskList.WebPart.   Its webpart assembly is

SourceCode.Workflow.TaskList, Version=4.0.0.0, Culture=neutral, PublicKeyToken=16a2c5aaaa1b130d

It looks like a gac assembly.  I figure I can just add it as a reference and then inherit from it.  I go to add the reference, and the assembly doesn’t show up as an available assembly:

image

(Tangent: It does surprise me that all of K2’s dll’s are in the namespace SourceCode.  I’m surprised it’s SourceCode.Workflow.Wizards instead of K2.Workflow.Wizards).

I figured I would get around this by <cough>hack</cough> copying the dll to a known location and referring to the dll directly instead of from the GAC. 

I found the dll  in c:\windows\assembly in windows explorer.  I then fired up cmd.exe and navigated to c:\windows\assmebly and typed:

dir *tasklist*.* /s

I found where the dll was living (C:\Windows\assembly\GAC_MSIL\SourceCode.Workflow.TaskList\4.0.0.0__16a2c5aaaa1b130d on my machine) and copied it to my lib folder.  I then added a reference to this dll and was on my way to step 2:

Step 2: Inherit from TaskListWebPartFactory and override the CreateChildControls Method

Create a class that inherits from TaskListWebPartFactory. 

Next, override the CreateChildControls method.  Inside this method, grab the current user and loop though his or her groups.  If the user belongs to the correct group, show the control, otherwise leave its visibility set to false.

protected override void CreateChildControls()
       {
           SPWeb currentWeb = SPContext.Current.Web;
           this.Visible = false;
           foreach (SPGroup group in currentWeb.CurrentUser.Groups)
           {
               if (group.Name == EDITOR_GROUP_NAME) //Specify the group name you want to check
               {
                   this.Visible = true ;
                   break;
               }
           }
           currentWeb.Dispose();
           base.CreateChildControls();
       }

Step 3: Create the supporting elements, features and .webpart file

The rest of this task is pretty straight forward.  Create a feature, elements and .webpart file to provision your new class.   I placed these in the proper 12 hive structure in a class library project and then used WSPBuilder to package it all up. I’ve listed the files below for reference.

Feature.xml

<?xml version="1.0" encoding="utf-8" ?>
<Feature xmlns="http://schemas.microsoft.com/sharepoint/"
         Id="YOURGUIDHERE"
         Title="Custom K2 WebParts"
         Scope="Site"
         Hidden="False"
         Version="1.0.0.0">

  <ElementManifests>
    <ElementManifest Location="elements.xml" />
    <ElementFile Location="TaskList.webpart" />
  </ElementManifests>

</Feature>

Elements.xml

 

<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Url="_catalogs/wp" RootWebOnly="TRUE">
    <File Url="TaskList.webpart" Type="GhostableInLibrary">
      <Property Name="Group"
                Value="Custom Web Parts" />
    </File>
  </Module>
</Elements>

tasklist.webpart

<?xml version="1.0" encoding="utf-8" ?>
<webParts>
  <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
    <metaData>
      <type name="CustomWebParts.SP.Assets.WebParts.TaskListWebPart, CustomWebParts.SP, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e485f8a858b358c3"/>
      <importErrorMessage>Error importing the Web Part.</importErrorMessage>
    </metaData>
    <data>
      <properties>
        <property name="Title" type="string">TaskList Web Part</property>
        <property name="ChromeType" type="chrometype">None</property>
      </properties>
    </data>
  </webPart>
</webParts>

Wrapping it all up

This was a pretty straight forward customization by inheriting from a class and overriding its methods.  The challenge came in finding which dll to inherit from (SP Designer is your friend) and grabbing a dll out of the gac that didn’t want to come (command line to the recue).

Technorati Tags: ,,
format-DateTime with XSL

I had to take a DateTime in the format of 2009-10-23 00:00:00 and convert it to 10/23/2009 using XSL.  XSL 1.0 doesn’t have any type of datetime formatting functions, so the following snippet should help anyone else in a similar predicament:

 

<xsl:element name="newdate">
         <xsl:call-template name="FormatDate">
           <xsl:with-param name="DateTime" select="@Date"/>
         </xsl:call-template>
       </xsl:element>

<xsl:template name="FormatDate">
   <xsl:param name="DateTime" />
   <xsl:variable name="Year">
     <xsl:value-of select='substring-before($DateTime,"-")'/>
   </xsl:variable>
   <xsl:variable name="NoYear">
     <xsl:value-of select='substring-after($DateTime,"-")'/>
   </xsl:variable>
   <xsl:variable name="Month">
     <xsl:value-of select='substring-before($NoYear,"-")'/>
   </xsl:variable>
   <xsl:variable name="DayWithTime">
     <xsl:value-of select='substring-after($NoYear,"-")'/>
   </xsl:variable>
   <xsl:variable name="Day">
     <xsl:value-of select='substring-before($DayWithTime," ")'/>
   </xsl:variable>
   <xsl:value-of select='$Month'/>
   <xsl:text>/</xsl:text>
   <xsl:value-of select='$Day'/>
   <xsl:text>/</xsl:text>
   <xsl:value-of select='$Year'/>
</xsl:template>

How to check your network connection state

If you need to check the state of your network connection in C#, I know of 2 ways (that I’m aware of) to do this:

 

1.  Steal from VB

You can use the VB “My” functions by importing the Microsoft.VisualBasic assembly into your project. 

In VB, you would normally use the following code:

My.Computer.Network.IsAvailable

In C#, you can use following code:

Microsoft.VisualBasic.Devices.Network network = new Microsoft.VisualBasic.Devices.Network();
Console.WriteLine(network.IsAvailable);

 

2. PInvoke

If you don’t want to bring a VB reference into your C# project (which shouldn’t really be a problem), you can always resort to PInvoking the native windows API’s.

Below is the code to code natively:

 

class Program
   {
       static void Main(string[] args)
       {
           Console.WriteLine(IsConnectedToInternet().ToString());
       }

       [DllImport("wininet.dll", SetLastError = true)]
       extern static bool InternetGetConnectedState(
          out InternetGetConnectedStateFlags Description, int ReservedValue);

       [Flags]
       enum InternetGetConnectedStateFlags
       {
           INTERNET_CONNECTION_MODEM = 0x01,
           INTERNET_CONNECTION_LAN = 0x02,
           INTERNET_CONNECTION_PROXY = 0x04,
           INTERNET_CONNECTION_RAS_INSTALLED = 0x10,
           INTERNET_CONNECTION_OFFLINE = 0x20,
           INTERNET_CONNECTION_CONFIGURED = 0x40
       }

       public static bool IsConnectedToInternet()
       {
           InternetGetConnectedStateFlags flags;
           var ret = InternetGetConnectedState(out flags, 0);
           Console.WriteLine(flags.ToString());
           return ret;
       }
   }

(I also updated pinvoke.net with this info)

Notes: 

1.  The Pinvoke method will give you an more detail by giving you an out parameter showing which connections are available to you

2.  These methods will only tell you if the network device is connected.  It won’t tell you if you have can get out to the internet.

Automated Attendant with the OCSDK Wrapper and WPF

Our office recently cut over to using Office Communications Server for our telephony needs, thereby replacing our old Nortel PBX.  One of the side effects of this was that we no longer have a phone in our lobby for visitors to use to call the receptionist.  Instead of purchasing a Polycom CX700 IP Phone and figuring a way to make sure it doesn't get stolen in our lobby, I wrote the Clarity Attendant app that allows visitors to search for consultants and place a call. 

image

 

WPF Keyboard Control

By far the hardest part was creating the WPF keyboard for users to enter partial names of the consultants they'd like to find.    This involves creating a keyboard button user control and dropping these onto a Keyboard control that would listen to click events and raise them up to it consumer as needed.

Keyboard Button Control

The Keyboard Button control is a container for all buttons on the keyboard.

XAML

I am by no means a designer.  In order to allow a designer to modify the buttons as needed, I've placed the button within a user control that a designer can then take into Expression Blend and design to their hearts content.  The code below is pretty simple.

 

image

Code

The keyboard button code-behind is pretty simple.  It exposes a properties for Text and ButtonType which can be set by the keyboard control.  The ButtonType helps us handle special keys such as space, backspace, and clear.When the button is clicked, I raise it as an event through the ButtonEventManager, described later.

using System.Windows;
using System.Windows.Controls;

namespace UCKiosk.UserControls
{
    /// <summary>
    /// Interaction logic for KeyboardButton.xaml
    /// </summary>
    public partial class KeyboardButton : UserControl
    {
        public string Text { get; set; }
        public ButtonType ButtonTypeEnum { get; set; }

        public static double WIDTH = 95;
        public static double HEIGHT = 60;

        public KeyboardButton()
        {
            InitializeComponent();
            Loaded += KeyboardButton_Loaded;
            MyButton.Click += MyButton_Click;
        }

        void KeyboardButton_Loaded(object sender, RoutedEventArgs e)
        {
            SetupDimensions();
            MyButton.Content = Text;
        }

        private void SetupDimensions()
        {
            if (double.IsNaN(Width))
                this.Width = WIDTH;
            if (double.IsNaN(Height))
                this.Height = HEIGHT;
            MyButton.Width = this.Width;
            MyButton.Height = this.Height;

            this.HorizontalAlignment = HorizontalAlignment.Left;
            this.VerticalAlignment = VerticalAlignment.Top;

            MyButton.FontSize = 18;
        }

        void MyButton_Click(object sender, RoutedEventArgs e)
        {
            ButtonClickedEventArgs evt = new ButtonClickedEventArgs(Text,ButtonTypeEnum);
            ButtonEventManager.Instance.OnButtonClickedEvent(evt);
        }

        public enum ButtonType
        {
            Backspace=1,
            Space=2,
            Clear=3          
        }
    }
}

WPF Keyboard Control

XAML

Now that we've crated our keyboard buttons control, we need to drop them onto a surface that will arrange these buttons for us.  I did this by creating 3 separate StackPanels and arranging the keyboard buttons horizontally in them. I added x:Name properties for the special controls since I'll be altering their sizes programtically in the code behind.  I've also tagged what type of buttons they are so that I can handle the special buttons in code.

<UserControl xmlns:my="clr-namespace:System.Windows.Controls.Primitives;assembly=PresentationFramework"  x:Class="UCKiosk.UserControls.WPFKeyboard"
    xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:UC="clr-namespace:UCKiosk.UserControls" >
    <Canvas>
        <StackPanel x:Name="Row1" Orientation="Horizontal">
            <UC:KeyboardButton Text="Q" />
            <UC:KeyboardButton Text="W" />
            <UC:KeyboardButton Text="E" />
            <UC:KeyboardButton Text="R" />
            <UC:KeyboardButton Text="T" />
            <UC:KeyboardButton Text="Y" />
            <UC:KeyboardButton Text="U" />
            <UC:KeyboardButton Text="I" />
            <UC:KeyboardButton Text="O" />
            <UC:KeyboardButton Text="P" />
        </StackPanel>
        <StackPanel x:Name="Row2" Orientation="Horizontal" >
            <UC:KeyboardButton Text="A" />
            <UC:KeyboardButton Text="S" />
            <UC:KeyboardButton Text="D"/>
            <UC:KeyboardButton Text="F" />
            <UC:KeyboardButton Text="G" />
            <UC:KeyboardButton Text="H" />
            <UC:KeyboardButton Text="J" />
            <UC:KeyboardButton Text="K" />
            <UC:KeyboardButton Text="L" />
            <UC:KeyboardButton x:Name="Backspace" Text="Backspace" ButtonTypeEnum="Backspace" />
        </StackPanel>
        <StackPanel x:Name="Row3" Orientation="Horizontal" >
             <UC:KeyboardButton Text="Z"/>
            <UC:KeyboardButton Text="X" />
            <UC:KeyboardButton Text="C" />
            <UC:KeyboardButton Text="V" />
            <UC:KeyboardButton Text="B" />
            <UC:KeyboardButton Text="N" />
            <UC:KeyboardButton Text="M" />
            <UC:KeyboardButton x:Name="Clear"   Text="Clear" ButtonTypeEnum="Clear" />
         </StackPanel>
        <StackPanel x:Name="Row4" Orientation="Horizontal" >
            <UC:KeyboardButton x:Name="Space" Text="Space" ButtonTypeEnum="Space"/>
        </StackPanel>
    </Canvas>
</UserControl>

Code

In the code-behind, I handle the events of the individual keyboard buttons, as described in the ButtonEventManager below, and set up some sizing.  

using System;
using System.Windows;
using System.Windows.Controls;

namespace UCKiosk.UserControls
{
    /// <summary>
    /// Interaction logic for WPFKeyboard.xaml
    /// </summary>
    ///
    public partial class WPFKeyboard : UserControl
    {
        public delegate void KeyPressedDelegate(object sender, ButtonClickedEventArgs e);
        public event KeyPressedDelegate KeyPressed;
        public WPFKeyboard()
        {
            InitializeComponent();
            InitializeButtonSizing();
            ButtonEventManager.Instance.ButtonClickedEvent += Instance_ButtonClickedEvent;
            Unloaded += WPFKeyboard_Unloaded;
        }

        private void InitializeButtonSizing()
        {
            var width = KeyboardButton.WIDTH;
            var height = KeyboardButton.HEIGHT;
            Clear.Width = width * 2;
            Space.Width = width * 9;
            Backspace.Height = height * 3;
            Row2.Margin = new Thickness(0, height, 0, 0); // Margin="15,30,0,0"
            Row3.Margin = new Thickness(0, height * 2, 0, 0); //Margin="30,60,0,0"
            Row4.Margin = new Thickness(0, height * 3, 0, 0); //Margin="0,90,0,0"
        }

        void Instance_ButtonClickedEvent(object sender, EventArgs e)
        {
            var args = (ButtonClickedEventArgs)e;
            if (KeyPressed != null)
                KeyPressed(sender, args);
        }

        void WPFKeyboard_Unloaded(object sender, RoutedEventArgs e)
        {
            ButtonEventManager.Instance.ButtonClickedEvent -= Instance_ButtonClickedEvent;
        }
    }
}

 

ButtonEventManager

The goal of the larger Keyboard control is to raise an event to its consumer that a key was clicked.  Without this class, each keyboard button would have its own button clicked event that the consumer of the keyboard control would have to wire up.  I handled this by creating a class called ButtonEventManager.  This class is responsible for maintaining a collection of all individual button clicked events and raising them to the consumer of the keyboard control.  This is done by using a EventHandlerList, which is a collection of delegates.  Note that I've implemented this class as a singleton so that there only exists one instance of this object per AppDomain.

 

using System;
using System.ComponentModel;

namespace UCKiosk.UserControls
{
    public sealed class  ButtonEventManager
    {
        private ButtonEventManager() { }
        public static readonly ButtonEventManager Instance = new ButtonEventManager();
        private EventHandlerList EventList = new EventHandlerList();
        private static object ButtonClickedEventKey = new object();

        public event EventHandler ButtonClickedEvent
        {
            add
            {               
                EventList.RemoveHandler(ButtonClickedEventKey, value);
                EventList.AddHandler(ButtonClickedEventKey, value);
            }
            remove
            {
                EventList.RemoveHandler(ButtonClickedEventKey, value);
            }
        }

        public void OnButtonClickedEvent(ButtonClickedEventArgs e) 
        {
            if (EventList[ButtonClickedEventKey] != null)
            {
                ((EventHandler)EventList[ButtonClickedEventKey]).Invoke(this, e);
            }
        }
    }

    public class ButtonClickedEventArgs : EventArgs
    {
        public string Text { get; set; }
        public KeyboardButton.ButtonType Type { get; set; }
        public ButtonClickedEventArgs(string text, KeyboardButton.ButtonType type )
        {
            Text = text;
            Type = type;
        }
    }
}

Attendant Application

The Attendant application contains our keyboard control we just made along with a listview to query results, a logo and a call button.

XAML

<Window xmlns:my="clr-namespace:System.Windows.Controls;assembly=PresentationFramework"  x:Class="UCKiosk.Home"
    xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:UC="clr-namespace:UCKiosk.UserControls"
    Title="Home" Width="1024" Height="768" Foreground="#FF74AFE8" xmlns:d="
http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Opacity="1">
    <Canvas >
        <Rectangle Stroke="#FF3184C3"  Width="1024" Height="768">
            <Rectangle.Fill>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FF74AFE8" Offset="0.379"/>
                    <GradientStop Color="#FF3184C3" Offset="0.746"/>
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        <Button FontSize="30"  x:Name="btnCall" Click="btnCall_Click" Height="58" Canvas.Left="888" Canvas.Top="18" Width="87" Content="Call"/>
        <UC:WPFKeyboard HorizontalAlignment="Center"  x:Name="objKeyboard" Margin="30,425,0,0"/>
        <TextBox TextChanged="txtInput_TextChanged" FontSize="18" x:Name="txtInput" Width="848.5" Height="39.5" Canvas.Left="34" Canvas.Top="380" />
        <ListView FontSize="14" x:Name="lvwResults" Height="356" Width="266.5" Canvas.Left="616" Canvas.Top="18" >
            <ListView.GroupStyle>
                <GroupStyle AlternationCount="2">
                    <GroupStyle.ContainerStyle>
                        <Style TargetType="{x:Type GroupItem}">
                            <Style.Triggers>
                                <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                                    <Setter Property="Background" Value="LightBlue"></Setter>
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </GroupStyle.ContainerStyle>
                </GroupStyle>
            </ListView.GroupStyle>
        </ListView>
        <Image  Width="379.6" Height="367.144" Canvas.Left="98" Source="ClarityAttendant.png" Stretch="Fill" Canvas.Top="6.856"/>
    </Canvas>
</Window>

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

Querying Active Directory

In order to search for users, I am using LDAP queries against Active Directory to retrieve all users that have Communicator enabled.  I do this upon startup of the application and then store the results in a list that I can so that I'm not taxing our domain controllers too heavily.  I store the user's name in a List<string> collection since I can search for users easily.  I store the SIP URI's for Office communicator in a hash table.  When a user clicks call, I look up the users's SIP URI via their displayName and place the call.

private void PopulateUsers()
        {
            try
            {
                var entry = new DirectoryEntry {Path = "LDAP://CN=Users,DC=YOURDOMAIN,DC=COM"};

                var searcher = new DirectorySearcher
                                   {
                                       SearchRoot = entry,
                                       Filter = "(&(objectClass=user)(cn=*)(displayName=*)(msRTCSIP-UserEnabled=*))"
                                   };
                searcher.PropertiesToLoad.Add("displayName");
                searcher.PropertiesToLoad.Add("msRTCSIP-PrimaryUserAddress");
                var results = searcher.FindAll();
                if (results.Count > 0)
                {
                    foreach (SearchResult result in results)
                    {
                        var adUser = (result.Properties["displayName"][0].ToString());
                        var sipURI = result.Properties["msRTCSIP-PrimaryUserAddress"][0].ToString();
                        _sipURIs.Add(adUser, sipURI);
                        _users.Add(adUser);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                MessageBox.Show(ex.Message);
            }
        }

Searching for Users

Searching for users is fairly simple.  We have to create our own delegate method to perform the searching and call it from the List's Find method

private void SearchForName()
{
    var results = _users.FindAll(ContainsUserText);
    lvwResults.ItemsSource = results;
    if (results.Count == 1)
        lvwResults.SelectedIndex = 0;
}

private bool ContainsUserText(string s)
{
    return s.ToUpper().IndexOf(txtInput.Text) >= 0;
}

 

Placing the call

Placing the call is probably the easiest part of this application, thanks to the OCSDKWrapper Project on CodePlex. I  simply look up the selected user's SIPURI and call the CallComputer() Method

     private void btnCall_Click(object sender, RoutedEventArgs e)
       {
           if (txtInput.Text == string.Empty)
               return;

           var sipUri = _sipURIs[(string) lvwResults.SelectedItem];
           MOCAutomation.Instance.CallComputer(sipUri);
           ResetAppState();
       }

Drop by the Blogger Lounge
Technorati Tags:

If you're at Tech Ed this week, come drop by the blogger lounge.  I'll be there tomorrow, Tuesday June 3rd from 3 - 4 PM.  There already appear to be some interesting people appearing in the lounge, such as Mike Hall, Scott Hanselman, and Billy Hollis to name a few.

I'm presenting at Tech Ed 08
Technorati Tags:

For any of you that are attending Tech Ed 2008 in Orlando this year, please make sure to attend the Windows Embedded Standard Session on June 3rd from 10:30 - 11:45 in room S310 G.  Jon Rauschenberger, our CTO, and I will take a small portion of the time do a "behind the scenes" look at how a demo that we wrote for the Windows Embedded team was built. It should be a fun session.  I hope you will learn a bit from our experiences in building this demo.

Please also drop by the Windows Embedded booth after the session to get an hands-on view of the demo we wrote.  I'll be happy to walk you through it.

Mix08 Day 3

Today was the last day at Mix.  As with many conferences, attendance is low and the content is not as high of caliber as the rest of the conference.  I'll give some quick reviews of the sessions I attended and then some closing thoughts about the conference.

Bring Your Data to Life with Windows Presentation Foundation

This session didn't bring anything new to the table with respect to WPF.  Anson Tsao recapped how WPF handles data binding and using templates.  He did have an interesting demo that showed off using a 2d interfaces within a 3d application.  He had two apps that were fully functional, but would rotate in and out primary focus based upon where the user's focus was.

Nerd + Art: Ten Code Snippets to Empower Your Inner Artist

This presenation was given by Nathan Dunlap and Robby Ingebretsen from Idenity Mine.  The goal of the talk was to give designers a few snippets of code that they could use to improve their user experiences  The snippets are available here.  It is a simple .vsi file that is geared mainly towards designers.  The snippets would look pretty familiar to most developers, but it should hopefully empower designers to take a look behind their xaml to better leverage all of WPF and silverlight

Effective User Interfaces in Windows Presentation Foundation and Microsoft Silverlight

This is the session that I will remember the most out of the entire conference.  This is not because of the content, but because of the scary way in which it ended.  it was delivered by a panel of engineers from Innotive  The session began with some mildly interesting interesting lessons learned about designing for touch displays.  The have built touch screen kiosks for Infiniti and have used the deep zoom technology to work with some large images.  Some of the struggles they mentioned were trying to get people to use large touch screens.  People see these large flat panel displays and don't readily understand they can touch them.  In an interesting tidbit, they mentioned how they solved this by paying a college student to go and touch the display every few minutes.  From this point, Peter Chang, Inntive's CTO took over to demo an app that didn't look quite ready.  He stumbled through the presentation that had a few bugs.  As he was presenting, he slumped forward and lost consciousness and hit the ground like a rag doll.  People tried attending to him, but he was completely limp.  It scared a lot of people in the session, including myself.  I asked if anyone was a doctor.  In retrospect, I should have known the answer to my own question... how many doctors would be attending this session.  Peter regained consciousness and sat down on a chair on stage.  After some encouragement, they brought him off stage and tended to him.   It turns out Peter was working very hard on the presentation for the last 3 days.   The talk pretty much wrapped up from there.  They mentioned he was ok.  He sure gave all that stayed around for the last session of the day a good scare.  I'm glad he's ok.

Final thoughts

  • Where's the new stuff????

When you compare the MIX to previous Mix's, there's really nothing new here... Silverlight 2.0?  Yeah, we all like to have new controls and a better model for laying out apps, but this pales in comparison to last year's introduction of Silverlight 1.0.

  • WIFI in hotel rooms is a joke

While there was free wifi at the conference, right after the last conference, we lost Internet connectivity.  After heading back to the hotel room at the Venetian, I'm still surprised how hotels still find a way to charge $10/day for "high-speed" Internet that is hardly any faster than what I can get from a tethered phone.  I'd love to see Hotels go the way that starbucks has with their wifi strategy.  If I only want to browse a small amount to check email or check my RSS

Technorati Tags:

feeds, give it to me for free.  If I plan on using it as my office for the day, I'll be happy to pay for quality Internet.

Mix08 Day 2

I attended 3 pretty good sessions and the keynote with SteveB and Guy Kawasaki.  I'll recap them below:

Building Great AJAX Applications from Scratch Using ASP.NET 3.5 and Visual Studio 2008 

This session felt like a recap session on some of the technologies the client-side AJAX support.  I am constantly impressed by the javascript intellisense support that is avialble inpeople are already using in their day-to-day development.  You can see his own recounting of the session here.  He talked about Muti-targeting, CSS support and LINQ to SQL for data access.  He next walked through a pretty simple example of using a server-side UpdatePanel to reduce screen flicker.  The talk started getting interesting when he demo-ed VS 2008. Once great thing he pointed out is that if you don't have javascript enabled in IE, IE8 is now able to turn it on by itself when you're in a debugging experience. He finished the session by showing off the auto-complete textbox that is part of the AJAX toolkit. Always cool to see how cleanly these tools work, at least in a demo setting.

Keynote with Guy Kawasaki and Steve Ballmer

The keynote was again preceded by our Johnny Cash impersonator. It turns out the kid was only 15... he could have fooled the majority of the audience that he was much older.  During the talk, Steve talked about how much MS wants Yahoo.  You get the impression that it is just a matter of time or stock price before the deal happens.  Steve hinted at what would change if the merger would happen, pointing out that there is no need to have 2 searches, and 2 mail applications.  He went on to talk about Apple.  On one hand, he knocked Guy Kawasaki's macbook air and their model for charging 30 center on the dollar for apps on the iphone., but on the other hand, was very happy that Apple licensed ActiveSync.  Lastly, Steve acknowledged that Vista created, and continues to create a bottleneck around other initiatives at Microsoft, perhaps explaining why IE has felt a bit of competition from Firefox.  Lastly, Steve got the crowd riled up with yet another monkey dance, chanting the greatness of web developers this time.  Steve's comment about a 50 cent cut at the end of the rant was a funny jab at apple.

Social Networks: Where Are They Taking Us?

This was a good panel discussion with some people from Plaxo, Facebook, amongst others.  I attended because Guy Kawasaki was again the moderator.  The main thing I got out of the talk was the sense of one trusted online presense once has.  The goal is to take the anonymity that people hide behind in the web away.  One way they all agreed might help is pushing the OpenID spec along.  It's sounds eerily similar MS's hailstorm, which has been around since the 90's.

Developing ASP.NET Applications Using the Model View Controller (MVC) Pattern  

This was probably one of the most entertaining sessions at Mix, delivered by Scott Hanselman.  I like the way MVC sits on top of ASP.NET.  It is structured in a way of take as much or as little of it as you like.  Looking at it, I don't see it as the silver bullet for all development, but it seems to fit very nicely into the TDD workflow.  If you're looking to get a application quickly to market, and like working with TDD, MVC seems to be the answer.  If you're working in a corporate environment with a lot of custom controls or datagrids, sticking with raw ASP.NET might work better.

Mix08 Day 1

Keynote

Things got kicked off this in true Vegas fashion with an artist performing Johnny Cash songs. 

Johnny Cash Performer

Ray Ozzie

 

Ray Ozzie came on stage and spoke for a short time about Microsoft's vision for the web going forward.  To sum things up, Microsoft sees the web as a hub that will connect all your devices together, from your PC to your  zune, to your media center pc.  Nothing new here in this message.  One interesting technology that was puts the rubber to the road is SQL Data services.  This is an interesting one.  I'm curious to see how willing corporations will be to put their data outside their own hosted machines. 

 Ray Ozzie

Scott Gu & Company

Scott Guthrie took the reigns over from Ray and began his 3 ring circus, not the least of which was his endearing juggling audition for cirque du soleil. 

 

IE8

  • Interop The number 1 point of IE8 was its dedication to interoperability.  In a complete about face, IE8 will be standards-compliant right out of the box.  They will be supporting CSS 2.1 by default and have been working with the WC3 to clear up the standards with 702 specific test cases they are supporting. 
  • Performance  IE8 has improved upon IE7's script performance.  I hope this turns into a real-world experience boost.  I have my doubts that it will render HTML as quickly as currently Firefox does.
  • HTML5 IE8 will support HTML 5, which includes some nice hash functionality that will hopefully not break that back button for AJAX-based web sties
  • IE8 Dev tools - There was an interesting demo of debuggig support within IE8 to inspect how and where styles are being manipulated, even if they are being manipulated at run time.  I didn't see much intellisense support in the debugging experience, but this will be a great help to developers.
  • IE8 Activities - Some neat demos showing how you could highlight an address in a web page, right click on the selection and see a windows live map of it inline with the page.  You also get the option to open the map in a separate tab.  Developers can easily modify their web pages to allow their activities to be integrated into the web.  They showed an example of viewing ebay listings inline.
  • WebSlices - Think of these as small pieces of the web that sit in your quick link bar.  They showed how you can view all your facebook updates in the quick link bar.  I wonder if this will get used much.  Do people still use the quick link bar?

Silverlight

IMG_1904

Scott gave the overview of the vision of how Silverlight 1.0 and 2.0 sit in the market place.  1.0 was meant to drive adoption of the plugin.  2.0 Beta 1 was announced and was aimed at improving the media experience, reducing the TCO of Silverlight, and better leveraging Silverlight for monetization.  Scott mentioned how Silverlight 1.1  was a 4.3 mb download.  I didn't hear how large Silverlight 2 will be when it ships. They aim to improve the media experience through adaptive streaming of Videos.  Silverlight will select the best bitrate based on the current network conditions.  If network conditions deteriorate, it can switch bitrates inline without a hiccup. They are aiming to reduce the TCO through Windows Media Services 2008.  This is a free product that can be installed into Windows Server 2008.  It allows administrators to burst video down to the user at the beginning of the video ,then only buffer only 10 seconds ahead of what they're watching.  This lessens the likelihood that the user would download the entire video, only to close it half way through watching it, thereby throwing away half of the server's bandwidth.  Scott lastly talked about monetizing the internet.  Scott and team showed off a Silverlight Add template that does sets up some of the plumbing for creating banner adds in silverlight.  Expression Encoder also supports burning in adds into the bottom of a video that overlays a portion of the video.  The ad can be a bitmap, video, or even xaml.

New Features

Microsoft really lowered the bar for entry to develop Silverlight applications with the introduction of controls for silverlight, including textbox, button, slider, a datagrid amongst others.  I went into a breakout session that went deeper into this and impressed me even more with the controls.  The controls are all open source and free for people to extend.  The datagrid seemed pretty well featured and customizable.  New layout controls such as the StackPannel were also introduced to help speed up laying out a Silverlight app.  Microsoft also mentioned that you can now write Silverlight controls as web parts for Sharepoint.  Silverlight also has some cool physics effects, such as a wave  effect that a developer can apply to a video.  All the rendering is pushed to the GPU, so CPU usage is low.

 

 

Technorati Tags:
Posted: Mar 06 2008, 10:33 AM by pwalke | with 3 comment(s)
Filed under:
Vegas baby, Vegas!

I'm heading to Las Vegas to attend Mix08.   It is being held at the Venetian on the from Wednesday until Friday.  I will be attending along with 6 other colleagues from Clarity.  I'm looking forward to some of the sessions about Silverlight 2.0  It's exciting to see far the product has come.  I am intrigued to see how it will can provide value to our clients.  I will be blogging my experiences on a daily basis throughout the conference.

...Peter

Posted: Mar 05 2008, 08:05 AM by pwalke | with no comments
Filed under:
Installing Windows Vista Beta1 on a Virtual PC

I had the joy over the last few days of installing Windows Vista, aka windows Longhorn, in a Virtual PC image.  Here are a few of my initial thoughts about the install and my first impressions of the spanking new OS:

 

You need memory

I initially tried installing the OS with just 768mb of Ram.  For 8 hours, I tried installing the about 5 times, and every time, my computer locked up (I think my memory might be bad).  I decided to try again after I got more memory.

 

Prompting for the CDkey twice

When installing the OS on a fresh hard drive, the setup program ends up asking you to enter the CD key twice.  I for some reason can not seem to enter a cd key correctly the 1st time, so this becomes tiresome. The first time you are prompted for the key is before you partition your new hard drive and a second after you reboot for the new partition to be read.  It seems like the partitioning prompts should take place before a cd key is entered.  This actually more than a slight annoyance as long as you don’t have to install the OS many times. Once I upped my memory to 1.25gb, the install went much smoother.  I was able to complete the install in about 2 hours

  

Installing Virtual Machine additions

Microsoft is touting the Windows Presentation foundation for its vector graphics along with other eye candy.  This sure is not the first impression one gets when installing from a virtual PC.  The first thing a user sees is an 800x600 4-bit color screen.  This sticks around until you install the Virtual Machine additions.  I was pleasantly surprised how well this install went.  After you install these additions, you can set the screen resolution to any normal resolution and color depth you like.

 

My advice

I would not try this install with anything less than 1 gig of ram.  1.5 is what you should be running. 

VPC’s for beta software

I love having Virtual PC’s set up with new beta software.  Some of the installs can really drain the excitement of a new product.  Virtual PC’s allow people to get their hands dirty real quick without the risk of trashing their system.  I recently installed the Virtual PC image for Team System from MSDN and am so impressed with how well that image is put together.  More on that later.