Process list in XAML plus a bit of virtualisation with the .NET Client Profile

It’s a public holiday in the UK and the weather’s turned sour but playing with XAML and WPF can still bring on a smile – I’m not claiming it’s anything new or clever but I enjoyed it ( paste into Kaxaml or XamlPad to view );

<Page
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:ctl="clr-namespace:System.Windows.Controls;assembly=PresentationFramework"
   xmlns:env="clr-namespace:System.Diagnostics;assembly=System"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   <Page.Resources>
    <Style x:Key="styleFontFamily" TargetType="{x:Type TextBlock}">
      <Setter Property="FontFamily" Value="Calibri"/>
    </Style>
    <Style x:Key="styleTitleFont" BasedOn="{StaticResource styleFontFamily}" TargetType="{x:Type TextBlock}">
      <Setter Property="FontSize" Value="24"/>
      <Setter Property="FontWeight" Value="Bold"/>
      <Setter Property="Foreground" Value="White"/>
    </Style>   
    <Style x:Key="styleProgressBar" TargetType="{x:Type ProgressBar}">
      <Setter Property="Foreground" Value="#FF0C4B5E"/>
      <Setter Property="HorizontalAlignment" Value="Stretch"/>
      <Setter Property="MinWidth" Value="192"/>
      <Setter Property="Margin" Value="0,2,2,2"/>
    </Style>
       <Style x:Key="styleSubGrid" TargetType="{x:Type Grid}">
      <Setter Property="Margin" Value="24,0,0,2"/>
    </Style>   
       <Style x:Key="styleSubFont" BasedOn="{StaticResource styleFontFamily}" TargetType="{x:Type TextBlock}">
      <Setter Property="FontSize" Value="18"/>
      <Setter Property="Foreground" Value="Black"/>
      <Setter Property="Margin" Value="0,0,5,0"/>
    </Style> 
   </Page.Resources>
   <Grid>
      <Grid.Resources>
         <ObjectDataProvider x:Key="myDataSource" MethodName="GetProcesses" ObjectType="{x:Type env:Process}"/>
      </Grid.Resources>
      <ListBox
        HorizontalContentAlignment="Stretch"
        DataContext="{StaticResource myDataSource}"
        ItemsSource="{Binding}">
        <ListBox.ItemTemplate>
          <DataTemplate>
              <Border Margin="0,2,0,4" BorderBrush="#FFCBCBCB" BorderThickness="1,1,3,3" CornerRadius="3,3,3,3">
                  <Border.Background>
                      <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                          <GradientStop Color="#FF00DA09" Offset="0"/>
                          <GradientStop Color="#FF0A7606" Offset="1"/>
                          <GradientStop Color="#FF8DF57B" Offset="0.467"/>
                      </LinearGradientBrush>
                  </Border.Background>
                  <Border.Effect>
                      <DropShadowEffect/>
                  </Border.Effect>
                  <StackPanel Width="Auto" Height="Auto" Grid.IsSharedSizeScope="True">
<TextBlock Style="{StaticResource styleTitleFont}" Text="{Binding ProcessName,StringFormat=Process {0}}"/>
                      <Grid Style="{StaticResource styleSubGrid}">
                          <Grid.ColumnDefinitions>
                              <ColumnDefinition Width="Auto" SharedSizeGroup="Col1"/>
                              <ColumnDefinition Width="*"/>
                          </Grid.ColumnDefinitions>                       
                          <TextBlock Style="{StaticResource styleSubFont}" Text="Process Id"/>
                        <TextBlock Style="{StaticResource styleSubFont}" Margin="0" Grid.Column="1" Text="{Binding Id}"/>
                      </Grid>
                      <Grid Style="{StaticResource styleSubGrid}">
                          <Grid.ColumnDefinitions>
                              <ColumnDefinition Width="Auto" SharedSizeGroup="Col1"/>
                              <ColumnDefinition Width="*"/>
                          </Grid.ColumnDefinitions>
                          <TextBlock Style="{StaticResource styleSubFont}" Text="Thread Count"/>
                        <ProgressBar Style="{StaticResource styleProgressBar}" Value="{Binding Path=Threads.Count, Mode=OneWay}"  Grid.Column="1" />
                      </Grid>
                      <Grid Style="{StaticResource styleSubGrid}">
                          <Grid.ColumnDefinitions>
                              <ColumnDefinition Width="Auto" SharedSizeGroup="Col1"/>
                              <ColumnDefinition Width="*"/>
                          </Grid.ColumnDefinitions>
                          <TextBlock Style="{StaticResource styleSubFont}" Text="Total CPU Usage (seconds)"/>
                          <ProgressBar Style="{StaticResource styleProgressBar}" Grid.Column="1" Maximum="600" Value="{Binding Path=TotalProcessorTime.Seconds, Mode=OneWay}"/>
                      </Grid>
                      <Grid Style="{StaticResource styleSubGrid}">
                          <Grid.ColumnDefinitions>
                              <ColumnDefinition Width="Auto" SharedSizeGroup="Col1"/>
                              <ColumnDefinition Width="*"/>
                          </Grid.ColumnDefinitions>
                          <TextBlock Style="{StaticResource styleSubFont}" Text="Virtual Memory Size"/>
                          <ProgressBar Style="{StaticResource styleProgressBar}" Grid.Column="1" Value="{Binding Path=VirtualMemorySize64, Mode=OneWay}" Maximum="314572800"/>
                      </Grid>
                  </StackPanel>
              </Border>
          </DataTemplate>
        </ListBox.ItemTemplate>
      </ListBox>
   </Grid>
</Page>

it ends up producing a process list something like this;

image

and the UI is a bit horrible but I was just building an example of binding and found the whole “code-free” nature of that particular lump of XAML to be a very positive thing.

The other thing that made me smile today was thinking about how I can use Windows XP mode in Windows 7 in order to run up IE6 on an operating system that doesn’t have any .NET Framework installed and then I can show how the .NET Client Profile installation works.

That is, I spring up a virtualised IE6 on my Windows 7 desktop by just having a shortcut;

image

and it spins up the virtual environment;

image

and that spins up IE 6;

image

and I can then point that virtualised IE at my local machine where my “Hello World” ClickOnce application lives;

image

and it launches the setup process which launches the .NET Client Profile setup;

image

which runs the bootstrapper and then goes off to download the client profile itself and install it;

image

and once that is run up it launches my ClickOnce setup;

image

and runs my app;

image

( not that the app itself is worth running 🙂 ).

Having done this, I can just shut down the Virtual PC and remove the Undo Disk and I’m back to a nice state where I don’t have any .NET Framework installed on that virtualised XP and so I can start again. Nice – there’s something about the desktop integration here that makes it a lot more friendly (for me) than having to switch off into separate windows for the Virtual PC bits and I really like what they’ve done with Undo Disks here – for me it’s much nicer than being asked “Do you want to save/discard?” each time I shutdown the VPC.

Asides;

  1. I made a short screencast about the .NET Client Profile a while ago. It’s up here.
  2. I noticed (and watched) a video the other day about .NET Framework V4.0 and WPF features and there’s a discussion in there about how the .NET Client Profile becomes more applicable in .NET 4.0 so it might be worth taking a look at that video. It’s here.