Category Archives: .Net

Microsoft .Net Framework

Silverlight Tiled Image Brush

HTML has repeat-x and repeat-y for years but Silverlight hasn’t managed to catch up. It’s elder sibling, WPF, has an ImageBrush which supports TileMode such as Tile, FlipX, FlipXY, FlipY.

This is rather handy if you want textured UI which is now common through out the web.

<!-- wpf only, this is not supported in Silverlight -->
<ListBox>
  <ListBox.Background>
     <ImageBrush ImageSource="grey_wash_wall.png" 
        TileMode="Tile" 
        Stretch="None" 
        ViewportUnits="Absolute" 
         Viewport="0,0,350,259"/>
      </ListBox.Background>
</ListBox>        

With a bit of help from existing code on pixel shaders (see references below), I managed to hone the code down to something that looks like the following:

<!-- wpf only, this is not supported in Silverlight -->
<ListBox Tile:Tile.Mode="Tile">
  <ListBox.Background>
     <ImageBrush ImageSource="grey_wash_wall.png" />
  </ListBox.Background>
</ListBox>        

There are a lot of assumptions going here. The attached property Tile:Mode walks down the visual tree and finds an element which has the background set to the same background as specified on the control. Since the ImageBrush doesn’t tile, we insert an Image into the visual tree. This image has a Tiled ShaderEffect attached and voila! Faked TiledImageBrush.

Caveats

If your template binds the Background to a Rectangle, this can be problematic as the the pixel shader will not clip properly.

Source

You can grab the code at https://github.com/teyc/SilverlightTiledImageBrush.

References

http://silverscratch.blogspot.com.au/2010/09/tiled-image-brush-for-silverlight.html

LightSwitch Extensions Made Easy VS2012

Lightswitch Extensions Made Easy by Jan Van der Haegen addresses some of the major pain points in developing LightSwitch Extensions. This extension tightens the edit-debug cycle. If you are in the business of developing shells, you owe a closer look at what Jan has done and use it in your workflow. It is a brilliant implementation.

Prerequisites

  1. Microsoft Visual Studio Premium
  2. Microsoft Visual Studio SDK (install via Tools/Extensions and Updates)
  3. Microsoft Lightswitch Extensions (install via Tools/Extensions and Updates)

Step 1: Installing the extension

The Lightswitch Extensions Made Easy provides a prebuilt extension that will load your custom classes via MEF. This means for most time, you will only need to build your dll, and not having to rebuild and reinstall an extension each time.

In Visual Studio 2012, under the Tools menu, select Extensions and Updates then in the Online category, search for “Lightswitch Extensions Made Easy”

ls-01

Step 2: Enabling the extension in your Lightswitch project

Select the Lightswitch project, and in the Properties context menu, enable the Lightswitch Extensions Made Easy project.

ls-02

Step 3: Set the shell

In the General Properties tab, select Edit Client Properties. Then set the Shell and Theme to “EasyShell” and “EasyTheme

ls-03

Step 4: Switch to File View in Solution Explorer

If you are a seasoned visual studio developer, you are probably wondering where are your normal project files. LightSwitch has hidden these away. This can be enabled in the Solution Explorer (see diagram).

ls-04

Step 5: Create a Lightswitch Extensions Project

Open an existing Lightswitch project, create your new Lightswitch Extensions Project and add it to your existing solution. This adds seven projects. Don’t get worried as you need to be only concerned with the Lspkg one:

  1. LightSwitchExtension1.Client
  2. LightSwitchExtension1.Client.Design
  3. LightSwitchExtension1.Common
  4. LightSwitchExtension1.Design
  5. LightSwitchExtension1.Lspkg
  6. LightSwitchExtension1.Server
  7. LightSwitchExtension1.Vsix

Step 6: Add a Shell item

Select the LightSwitchExtension1.Lspkg project, and Add New Item. Select “Shell”. This will add a shell xaml to your LightSwitchExtension1.Client project.

Step 7: Set the shell’s access to public

Change the shell’s access modifier from internal to public. This will enable EasyShell to load your code.

namespace LightSwitchExtension1.Presentation.Shells.Components
{
    [Export(typeof(IShell))]
    [Shell(DockableShell.ShellId)]
    <del>internal</del> public class DockableShell : IShell
    {
    }

Step 8: Reference the LightswitchExtension1.Client project

In the Lightswitch project, add a reference to the LightswitchExtension1.Client project.

Add an EasyShellExporter class to the Lightswitch project’s Client subproject

namespace LightswitchTest
{
    using ExtensionsMadeEasy.ClientAPI.Shell;
    using LightSwitchExtension1.Presentation.Shells.Components;
    
    public class DockableShellExporter: EasyShellExporter<DockableShell>
    {

    }
}

Step 9: Design the shell

Refer to MSDN’s Creating Shell Extension Walkthrough. In particular, look at the second listing at Define a Shell.

In particular, you should observe that the sample shell contains the following items:

<ListBox x:Name="CommandPanel" 
  ShellHelpers:ComponentViewModelService.ViewModelName="Default.CommandsViewModel"
  ItemsSource="{Binding ShellCommands}" />

<controls:TreeView x:Name="ScreenTree"
   ShellHelpers:ComponentViewModelService.ViewModelName="Default.NavigationViewModel"
   ItemsSource="{Binding NavigationItems}" />

<!-- The individual TabItem         -->
<!-- controls are created in code.  -->
<controls:TabControl x:Name="ScreenArea" />

How to call a XML Service without adding Service Reference

string url = "http://etcetcetc";
HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create(new Uri(url));
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();

XmlDocument doc = new XmlDocument();
doc.Load(resp.GetResponseStream());
var totals = doc.SelectSingleNode("/root/eventFundraisingTotals_collection/eventFundraisingTotals");
var verifiedGoal = totals.SelectSingleNode("eventVerifiedFundraisingGoal/text()").Value;
var unverifiedGoal = totals.SelectSingleNode("eventUnVerifiedFundraisingGoal/text()").Value;
var statusMessage = totals.SelectSingleNode("statusMessage/text()").Value;

Adding Global Behaviors to Silverlight Controls

Take a look at the two buttons below, and hover your mouse over them. You’ll notice that the buttons hide themselves.

However, when you take a look at the XAML, it is not obvious how this is implemented.

<UserControl x:Class="GlobalBehavior.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"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:local="clr-namespace:GlobalBehavior"
    mc:Ignorable="d"             
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">
        
        <Button Content="Click Me" Margin="36,28,0,0" HorizontalAlignment="Left" Width="112" Height="47" VerticalAlignment="Top" />
        <Button Content="Click Me" Margin="133,104,0,0" HorizontalAlignment="Left" Width="112" Height="47" VerticalAlignment="Top" />

    </Grid>
</UserControl>

This is done by attaching a behavior to the default Button style. There is a little wrinkle to the trick. The style setters by default is not able to set complex attached dependency properties. However, it can handle simple dependency properties. So, we’d write a simple depedency property that can be attached like this:


        <Style TargetType="Button">
            <Setter Property="local:HideButtonBehavior.ButtonBehaviors" Value="True" />
        </Style>

and the ButtonBehaviors dependency property sets the actual Behaviors on the button.

namespace GlobalBehavior
{
    using System;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Interactivity;
    using System.Windows.Media;
    using System.Windows.Media.Animation;

    public partial class HideButtonBehavior : Behavior<FrameworkElement>
    {        
        #region HideButtonBehavior.ButtonBehaviors depedency property

        public static bool GetButtonBehaviors(DependencyObject obj)
        {
            return (bool)obj.GetValue(ButtonBehaviorsProperty);
        }

        public static void SetButtonBehaviors(DependencyObject obj, bool value)
        {
            obj.SetValue(ButtonBehaviorsProperty, value);
        }

        // Using a DependencyProperty as the backing store for ButtonBehaviors. 
        public static readonly DependencyProperty ButtonBehaviorsProperty =
            DependencyProperty.RegisterAttached("ButtonBehaviors",
            typeof(bool), typeof(Button), new PropertyMetadata(false, ButtonBehaviorsChanged));

        private static void ButtonBehaviorsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var behaviors = Interaction.GetBehaviors(d);
            var existingBehavior = behaviors.FirstOrDefault(b => b.GetType() ==
              typeof(HideButtonBehavior)) as HideButtonBehavior;
            if ((bool)e.NewValue == false &amp;&amp; existingBehavior != null)
            {
                behaviors.Remove(existingBehavior);
            }
            else if ((bool)e.NewValue == true &amp;&amp; existingBehavior == null)
            {
                /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
                /* !!! THE REST ARE ALL BOILERPLATE. THE REAL GOODNESS IS HERE !!! */
                behaviors.Add(new HideButtonBehavior());
                /* !!!                                                         !!! */
                /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
            }
        }

        #endregion

    }
}

and for completeness, here’s the code for the silly Button behavior.

namespace GlobalBehavior
{
    using System;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Interactivity;
    using System.Windows.Media;
    using System.Windows.Media.Animation;

    public partial class HideButtonBehavior : Behavior<FrameworkElement>
    {
        #region Custom Button Behavior

        protected override void OnAttached()
        {
            base.OnAttached();
            Button button = this.AssociatedObject as Button;
            button.RenderTransform = new ScaleTransform();
            button.MouseMove += button_MouseMove;
        }

        protected override void OnDetaching()
        {
            Button button = this.AssociatedObject as Button;
            button.MouseMove -= button_MouseMove;
            base.OnDetaching();
        }

        void button_MouseMove(object sender, MouseEventArgs e)
        {
            DoubleAnimationUsingKeyFrames anim = new DoubleAnimationUsingKeyFrames();
            anim.KeyFrames.Add(new LinearDoubleKeyFrame() { Value = 0.0, KeyTime = TimeSpan.FromMilliseconds(150) });
            anim.KeyFrames.Add(new LinearDoubleKeyFrame() { Value = 0.0, KeyTime = TimeSpan.FromMilliseconds(2000) });
            anim.KeyFrames.Add(new LinearDoubleKeyFrame() { Value = 1.0, KeyTime = TimeSpan.FromMilliseconds(2150) });

            Storyboard.SetTarget(anim, this.AssociatedObject);
            Storyboard.SetTargetProperty(anim, new PropertyPath("(UIElement.RenderTransform).(ScaleTransform.ScaleY)"));

            Storyboard sb = new Storyboard();
            sb.Children.Add(anim);
            sb.Begin();
        }
        #endregion

    }
}

Acknowledgements

This technique is first discovered by julmar

Reactive Extensions Pop Up Toaster

I’m experimenting with RX, and this is an early attempt at expressing the following logic.

  • Start to slide the toaster into view, then fade it out, and remove the toaster from visual tree
  • If a mouse enters the toaster, then pause the sliding, and pause the fading out, and fade it in. Also, wait for mouse to leave
  • When mouse leaves, resume sliding toaster, and fade out the toaster.
        private void rxPop()
        {
            Rectangle toaster = (Rectangle)this.FindName("toaster1");
            Thickness newToasterPosition = new Thickness(
                 toaster.Margin.Left, toaster.Margin.Top,
                 toaster.Margin.Right, toaster.Margin.Bottom + toaster.Height);

            /* Animations */
            Storyboard slideInAnimation = slideTo(toaster,
                newToasterPosition,
                TimeSpan.FromMilliseconds(450));

            Storyboard fadeInAnimation = animateOpacity(toaster, 1.0, TimeSpan.FromMilliseconds(150));

            Storyboard fadeOutAnimation = animateOpacity(toaster, 0.0, TimeSpan.FromSeconds(3));
            
            /* Events */
            var mouseEnter = Observable.FromEventPattern<MouseEventHandler, MouseEventArgs>
                (h => toaster.MouseEnter += h,
                 h => toaster.MouseEnter -= h);

            var mouseOut = Observable.FromEventPattern<MouseEventHandler, MouseEventArgs>
                (h => toaster.MouseLeave += h,
                 h => toaster.MouseLeave -= h);            

            /* Business logic: mouseEnter/mouseLeave should pause/restart animations */
            var mouseEnterSubscription = mouseEnter
                .ObserveOnDispatcher()
                .Do(mouseEnterEventArgs =>
                {
                    fadeOutAnimation.Pause();
                    fadeInAnimation.Begin();
                    slideInAnimation.Pause();
                })
                .Select(e => mouseOut)
                .Switch()
                .Do(mouseLeaveEventArgs =>
                {
                    fadeOutAnimation.Begin();
                    fadeInAnimation.Stop();
                    slideInAnimation.Resume();
                })
                .Subscribe();

            /* Business logic: slideIn then fadeOut then remove from visual tree */
            slideInAnimation
                .BeginUntilDone()
                .Select(slideInCompletedEvent =>
                    fadeOutAnimation.BeginUntilDone())
                .Switch()
                .Subscribe(fadeOutAnimationCompletedEvent =>
                {
                    mouseEnterSubscription.Dispose();

                    // remove from visual tree
                    (toaster.Parent as Panel).Children.Remove(toaster);
                });

        }

        private Storyboard slideTo(FrameworkElement toaster, Thickness newMargin, TimeSpan duration)
        {
            DoubleAnimation slide = new DoubleAnimation()
            {
                From = newMargin.Bottom - toaster.Margin.Bottom,
                To = 0.0,
                Duration = duration,
            };
            toaster.Margin = newMargin;
            Storyboard.SetTarget(slide, toaster);
            Storyboard.SetTargetProperty(slide,
                new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)"));
            Storyboard slideboard = new Storyboard();
            slideboard.Children.Add(slide);
            return slideboard;
        }

        private Storyboard animateOpacity(FrameworkElement toaster, double target, TimeSpan duration)
        {
            DoubleAnimation fade = new DoubleAnimation()
            {
                To = target,
                Duration = duration,
            };

            Storyboard.SetTarget(fade, toaster);
            Storyboard.SetTargetProperty(fade,
                new PropertyPath("Opacity"));
            Storyboard slideboard = new Storyboard();
            slideboard.Children.Add(fade);
            return slideboard;
        }

    public static class RxExtensions
    {
        public static IObservable<EventPattern<EventArgs>> BeginUntilDone(this Storyboard sb)
        {
            var tmp = Observable.FromEventPattern(
                h => sb.Completed += h,
                h => sb.Completed -= h);
            sb.Begin();
            return tmp;
        }
    }

Silverlight – faster compilation by reducing xap file size

Suppose we have a Silverlight Solution that has tens of projects. A lot of time is spent building the .xap file. Every time a DLL is touched, the entire solution is re-xapped.

To avoid this, we can use Assembly Library Caching. However, this is not always ideal. Each of the projects might be only a tiny DLL, and it is a lot of work. Each change in version number will require the .extmap.xml be updated. Furthermore, if we don’t change the version number, we might end up with Silverlight loading an older version, and we end up with “Symbol not loaded” in the debugger.

There is an alternative.

  1. Since we typically work on one assembly at a time, set all the assemblies we don’t care about to CopyLocal=False
  2. Then, (optional) in the Configuration Manager, uncheck the “Build” option for these DLLs as well.
  3. Next, zip up these DLLs, let’s call it library.zip. It should not have any directory structure at all e.g.

    mylibrary01.dll
    mylibrary02.dll
  4. Then in the Properties/AppManifest.xml of the main project, add the following entry
    <Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Deployment.Parts>
        </Deployment.Parts>
      <Deployment.ExternalParts>
        <ExtensionPart Source="library.zip"/>
      </Deployment.ExternalParts>  
    </Deployment>
    
  5. You are done.

When you start up this project, you’ll notice that compiling can be very fast, as xapping will skip all the files that have CopyLocal=false.

Visual Studio 2012 and Microsoft XNA Game Studio

Ryan Lange has provided a handy guide how to get XNA studio projects to run in Visual Studio 2012. But this is on the proviso you already have Microsoft XNA Game Studio already installed on the machine.

I had a clean machine with a VS 2012 install, and as I soon found out, installing XNA game studio is no trivial matter. The 43 MB XNA Game Studio has a dependency on Visual C# 2010 Express, which in turn installs SQL Server Express and a load of junk that threatens to use 898 Mb of disk space.

Luckily, I already had XNA Game Studio installed on another machine, and the process was reasonably straightforward.

  1. Copy the files from C:\Program Files (x86)\Microsoft XNA\XNA Game Studio\v4.0
  2. Make the following Registry Entry (required for BuildXAct task):

    Windows Registry Editor Version 5.00

    [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\XNA\Game Studio\v4.0]
    “InstallPath”=”C:\\Program Files (x86)\\Microsoft XNA\\XNA Game Studio\\v4.0″

  3. Copy the files from C:\Program Files (x86)\MSBuild\Microsoft\XNA Game Studio
  4. Register the XNA assemblies in the GAC using gacutil
    cd C:\Program Files (x86)\Microsoft XNA\XNA Game Studio\v4.0\References\Windows\x86
    gacutil /i Microsoft.Xna.Framework.Avatar.dll
    REM repeat for each of the DLL in this directory
    
  5. I’m not sure if this is entirely necessary – Run the Redistributable MSI in
    C:\Program Files (x86)\Microsoft XNA\XNA Game Studio\v4.0\Redist\XNA FX Redist\xna_fxredist.msi

And that was about it. I was able to compile StarWarrior from Artermis Entity Component Framework.

Let me know if you find anything else.

Tutorial – Validating data with Caliburn.Micro

Purpose

This tutorial explains how to validate a textbox using Caliburn Micro. In this example, we are creating a logon screen and we wish to validate the username and password are not blank before trying to authenticate.

View Model

By convention, the view model must be in the ViewModels namespace. I have inherited from Screen here, but you may inherit from PropertyChangeBase.

namespace SecureDocumentStore.ViewModels
{
    using Caliburn.Micro;
    using System.ComponentModel.DataAnnotations;
    using System.Diagnostics;

    public class LogonViewModel : Screen
    {
    }
}

Next, we add the UserName and Password properties. I’ve only included the UserName one for brevity. Observe how we annotate the username property with the Required attribute. In addition, I’ve marked the property setter with DebuggerNonUserCode to stop the Validation exception from breaking into the debugger. You may want to remove this.

There is a code snippet available to reduce the effort of creating a property like this.

        private string _UserName;

        [Required]
        public string UserName
        {
            get { return _UserName; }

            [DebuggerNonUserCode]
            set
            {
                Validator.ValidateProperty(value,
                    new ValidationContext(this, null, null) { MemberName = "UserName" });
                _UserName = value;
                NotifyOfPropertyChange(() => UserName);
            }
        }

View

The View is reasonably straightforward, just a control with two text boxes and a button.

<UserControl x:Class="SecureDocumentStore.Views.LogonView"
    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"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">
        <TextBlock Text="Logon Window" />
        <TextBox x:Name="UserName" Margin="10,87,10,176" />
        <TextBox x:Name="Password" Margin="10,140,10,123" />
        <Button x:Name="SignOn" Content="Sign On" />
    </Grid>
    
</UserControl>

SignOn method

The button is named SignOn, and by convention, Caliburn.Micro looks for the method called SignOn on the View Model. We will need to call Validator.ValidateObject to run a final pass of validation on all properties.

public void SignOn()        
{
   Validator.ValidateObject(this, new ValidationContext(this));
   // TODO: authenticate UserName, Password         
}

Final wrinkle

The Validation framework requires controls to implement ValidatesOnExceptions. By default, this is not set in Caliburn.Micro, unless your c
view model implements INotifyDataErrorInfo. Therefore you have two choices.

First, you can call this when the application starts up.


// using Caliburn.Micro;

public App()
{
  InitializeComponent();

  ConventionManager.ApplyValidation = (binding, viewModelType, property) =>
  {
   binding.ValidatesOnExceptions = true;
  };
}

Alternately, you can add implement INotifyDataErrorInfo

public class LogonViewModel: Screen, INotifyDataErrorInfo
{
    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

    public System.Collections.IEnumerable GetErrors(string propertyName)
    {
        // todo
    }

    public bool HasErrors
    {
        get { // todo }
    }
}

Downloads

RazorEngine and ASP.net WebPages v2

I use RazorEngine for generating emails. Unfortunately, for a recent project, it has a dependency on ASP.net Web Pages v 1. The best way to install this on a machine that doesn’t already have v1 in the GAC is to issue a codeBase directive.

You will also need to copy C:\Program Files\Microsoft ASP.NET\ASP.Net Web Pages\v1.0\Assemblies\System.Web.Razor.dll to bin\v1

  <runtime>
    <assemblyBinding  xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <!--<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />-->
        <codeBase version="1.0.0.0" href="bin\v1\System.Web.Razor.dll" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>