Second Stanza

May 2, 2009

Silverlight Color Picker Control

Filed under: Silverlight — Tags: — dfbaskin @ 2:21 pm

I’m not sure why a color picker was not included in Silverlight since it seems like such a common control. However, I needed one so I took a look at my options. Plenty of examples exist so I decided to take the work started by Page Brooks (here, here, and here) and incorporate the Modal Popup functionality.

I ended up with a PopupColorPicker control. Here’s a picture of it in all of its popped-up glory:

Popup Color Picker Control

This control uses the Hue/Saturation/Value color space to translate colors to and from RGB values (through the HSVColor structure that is similar to the Color structure). The control also includes selecting a value for the opacity.

The control initially displays a color display box/button, which opens the Popup panel to select the color, and a text box, which a user can enter in an ARGB value directly. When the user clicks the color display button, the Popup panel is displayed (as shown above). On the left the user selects the hue, in the middle the saturation and value, and on the right the opacity.

The source code can be downloaded from CodePlex.

Hope this is useful!

Advertisement

Silverlight Modal Popup

Filed under: Silverlight — Tags: — dfbaskin @ 1:18 pm

The Popup control in Silverlight is not, as you might think, like a modal dialog box where other portions of the application are disabled while the dialog is displayed. It is more like an overlay where the contents of the Popup control are displayed on top of everything else in the control. However, lower level controls are still active.

If you need something more like a modal dialog box, you can simulate this in Silverlight by including a rectangle in your Popup that spans over the entire display area of the control.

I’ve taken this idea and encapsulated it into a ModalPopup control. The control can be used similarly to the Popup control, such as in the following example:

<stz:AutoSizeUserControl x:Class="Demo.ModalPopupDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:stz="clr-namespace:Stanza.Silverlight.Controls;assembly=Stanza.Silverlight.Controls" Width="800" Height="600" MinWidth="300" MinHeight="200" ExtraHeight="140" ExtraWidth="20" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
	<Grid x:Name="LayoutRoot" Background="White">
		<Grid>
			<Rectangle Stroke="#FF0000FF" RadiusX="32" RadiusY="32" StrokeThickness="2">
				<Rectangle.Fill>
					<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
						<GradientStop Color="#FF000000"/>
						<GradientStop Color="#FFFFFFFF" Offset="1"/>
					</LinearGradientBrush>
				</Rectangle.Fill>
			</Rectangle>
			<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
				<Button Width="140" Height="26" x:Name="showDefaultBtn" Content="Show (Fixed)"/>
				<Button Width="140" Height="26" x:Name="showRelativeBtn" Content="Show (Relative)"/>
				<Button Width="80" Height="26" x:Name="showFullScreen" Content="Full Screen"/>
			</StackPanel>
		</Grid>
		<stz:ModalPopup x:Name="popupPanel" Height="200" Width="220" BackgroundOpacity="0.25" BackgroundFill="Green" Left="200" Top="100" d:IsHidden="True">
            <Border x:Name="popupPanelGrid" BorderThickness="4,4,4,4" Background="Green" BorderBrush="Red" Width="220" Height="200">
				<Grid>
					<Grid.RowDefinitions>
						<RowDefinition/>
						<RowDefinition/>
					</Grid.RowDefinitions>
					<Grid.ColumnDefinitions>
						<ColumnDefinition/>
						<ColumnDefinition/>
					</Grid.ColumnDefinitions>
					<Ellipse Margin="10" Grid.RowSpan="2" Grid.ColumnSpan="2">
						<Ellipse.Fill>
							<RadialGradientBrush GradientOrigin="0.25,0.25">
								<GradientStop Offset="0.25" Color="White" />
								<GradientStop Offset="1.0" Color="Red" />
							</RadialGradientBrush>
						</Ellipse.Fill>
					</Ellipse>
					<Button Width="70" Height="26" x:Name="closeBtn" Content="Close" Grid.Row="1" Grid.Column="1"/>
				</Grid>
            </Border>
		</stz:ModalPopup>
	</Grid>
</stz:AutoSizeUserControl>

The popup panel itself can be opened and closed using code like:

...
    showRelativeBtn.Click += new RoutedEventHandler( showRelativeBtn_Click );
    closeBtn.Click += new RoutedEventHandler( closeBtn_Click );
...

    void showRelativeBtn_Click( object sender, RoutedEventArgs e )
    {
        Point pt = showRelativeBtn.GetAbsolutePosition();
        pt.X += showRelativeBtn.Width / 2;
        pt.Y += showRelativeBtn.Height / 2;
        popupPanel.OpenPopup( pt );
    }

    void closeBtn_Click( object sender, RoutedEventArgs e )
    {
        popupPanel.ClosePopup();
    }

The GetAbsolutePosition() method is an extension method that allows you to get the position of the UIElement object relative to the entire Silverlight display area.

The source code can be downloaded from CodePlex.

Resizing a Silverlight Control within the Browser

Filed under: Silverlight — Tags: — dfbaskin @ 12:27 pm

A common user interface technique in a web page is to expand the contents of the page to the size of the browser window. There are solutions for doing this in both CSS or Javascript. A Silverlight control may also be resized in this way and since a Silverlight control can access the Browser’s DOM (unless permission is explicitly denied), resizing can be handled within the control itself.

To do so, the control will need to be notified of the browser’s OnResize event, which can be attached using the following code:

...
HtmlPage.Window.AttachEvent( "onresize", new EventHandler<HtmlEventArgs>( BrowserWindow_Resized ) );
...

void BrowserWindow_Resized( object sender, HtmlEventArgs e )
{
    AdjustControlSize();
}

Then, you can determine the new size of the browser window using a technique similar to what might be used in Javascript:

        public static bool IsIECSSCompatibleMode
        {
            get
            {
                bool isCompatibleMode = false;
                string mode = HtmlPage.Document.GetProperty( "compatMode" ) as String;
                if( ( mode != null ) && ( String.Compare( mode, 0, "CSS1", 0, 4, StringComparison.InvariantCultureIgnoreCase ) == 0 ) )
                    isCompatibleMode = true;
                return isCompatibleMode;
            }
        }

        public static double BrowserWindowWidth
        {
            get
            {
                object w = HtmlPage.Window.GetProperty( "innerWidth" );
                if( w != null )
                    return Convert.ToDouble( w );
                else if( IsIECSSCompatibleMode )
                {
                    w = HtmlPage.Document.Body.Parent.GetProperty( "clientWidth" );
                    if( w != null )
                        return Convert.ToDouble( w );
                }
                else
                {
                    w = HtmlPage.Document.Body.GetProperty( "clientWidth" );
                    if( w != null )
                        return Convert.ToDouble( w );
                }
                return double.NaN;
            }
        }

        public static double BrowserWindowHeight
        {
            get
            {
                object h = HtmlPage.Window.GetProperty( "innerHeight" );
                if( h != null )
                    return Convert.ToDouble( h );
                else if( IsIECSSCompatibleMode )
                {
                    h = HtmlPage.Document.Body.Parent.GetProperty( "clientHeight" );
                    if( h != null )
                        return Convert.ToDouble( h );
                }
                else
                {
                    h = HtmlPage.Document.Body.GetProperty( "clientHeight" );
                    if( h != null )
                        return Convert.ToDouble( h );
                }
                return double.NaN;
            }
        }

I’ve encapsulated this technique into a Silverlight control called AutoSizeUserControl. This control is derived from the standard UserControl and automatically resizes itself based on changes to the size of the browser window. It can be used simply as a replacment for the UserControl:

<stz:AutoSizeUserControl x:Class="Demo.AutoSizeDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:stz="clr-namespace:Stanza.Silverlight.Controls;assembly=Stanza.Silverlight.Controls" Width="800" Height="600" MinWidth="300" MinHeight="200" ExtraHeight="164" ExtraWidth="20">
    <Grid x:Name="LayoutRoot" Background="White">
		<Rectangle Stroke="#FF000000" RadiusX="16" RadiusY="16" StrokeThickness="4" >
			<Rectangle.Fill>
				<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
					<GradientStop Color="#FF000000"/>
					<GradientStop Color="#FFFFFFFF" Offset="1"/>
				</LinearGradientBrush>
			</Rectangle.Fill>
		</Rectangle>
		<Grid HorizontalAlignment="Center" VerticalAlignment="Center" Width="250" Height="120">
			<Grid.RowDefinitions>
				<RowDefinition/>
				<RowDefinition/>
				<RowDefinition/>
				<RowDefinition/>
			</Grid.RowDefinitions>
			<Grid.ColumnDefinitions>
				<ColumnDefinition/>
				<ColumnDefinition/>
				<ColumnDefinition/>
				<ColumnDefinition/>
			</Grid.ColumnDefinitions>
			
			<TextBlock Text="Browser Window" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.ColumnSpan="2"/>
			<TextBlock Text="Width:" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center"/>
			<TextBox Text="0" x:Name="browserWidthBox" Grid.Column="1" IsReadOnly="True" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center" MinWidth="40"/>
			<TextBlock HorizontalAlignment="Center" Text="Height:" Grid.Row="2" Grid.Column="0" VerticalAlignment="Center"/>
			<TextBox Text="0" x:Name="browserHeightBox" Grid.Column="1" Grid.Row="2" IsReadOnly="True" HorizontalAlignment="Center" VerticalAlignment="Center" MinWidth="40"/>
			
			<TextBlock Text="Silverlight Control" Grid.Row="0" Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.ColumnSpan="2"/>
			<TextBlock Text="Width:" Grid.Row="1" Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center"/>
			<TextBox Text="0" x:Name="controlWidthBox" Grid.Column="3" IsReadOnly="True" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center" MinWidth="40"/>
			<TextBlock HorizontalAlignment="Center" Text="Height:" Grid.Row="2" Grid.Column="2" VerticalAlignment="Center"/>
			<TextBox Text="0" x:Name="controlHeightBox" Grid.Column="3" Grid.Row="2" IsReadOnly="True" HorizontalAlignment="Center" VerticalAlignment="Center" MinWidth="40"/>
			
			<Button Grid.Row="3" Content="Full Screen" Grid.ColumnSpan="2" Grid.Column="1" Width="80" Height="24" x:Name="fullScreenButton"/>
			
		</Grid>
    </Grid>
</stz:AutoSizeUserControl>

Source code can be downloaded from CodePlex.

Second Stanza Source Code Repository

Filed under: .NET Development, Silverlight — dfbaskin @ 11:46 am

I’ve created a project on CodePlex to store the source code I’ve publish within this blog. The project is located at secondstanza.codeplex.com. The first set of source code is a set of useful Silverlight controls. Enjoy!

April 29, 2009

Detecting Design Mode in Silverlight Controls

Filed under: Silverlight — Tags: — dfbaskin @ 10:26 am

Here are a couple of links about the issues with detecting when a control is design mode (within Expression Blend or Visual Studio):

February 26, 2009

SetPrincipalPolicy in Unit Tests

Filed under: .NET Development, Testing — Tags: — dfbaskin @ 9:42 pm

A while back, I noticed that this test always fails in Visual Studio 2008 w/SP1:


[TestClass]
public static class TestInfo
{
    [AssemblyInitialize]
    public static void InitializeTesting( TestContext testContext )
    {
        AppDomain.CurrentDomain.SetPrincipalPolicy(
             System.Security.Principal.PrincipalPolicy.WindowsPrincipal );
        Assert.IsInstanceOfType(
             System.Threading.Thread.CurrentPrincipal,
             typeof(System.Security.Principal.WindowsPrincipal) );
    }
}

According to the documentation:

Setting this value will only be effective if you set it before using the Thread.CurrentPrincipal property. For example, if you set Thread.CurrentPrincipal to a given principal (for example, a generic principal) and then use the SetPrincipalPolicy method to set the PrincipalPolicy to WindowsPrincipal, the current principal will remain the generic principal.

So it’s apparent that MS Test is doing just that and causing the test to fail. This was confirmed in the Microsoft Connect item I posted about it:

This is by design. We noticed this when doing testing of the fix for SP1 and made a trade off. The tradeoff is a performance hit that we would take each time we invoke a method in the test assembly verses using a simple workaround. The workaround is to explicitly set the “System.Threading.Thread.CurrentPrincipal”.

We use the Thread.CurrentPrincipal policy prior to invoking any test method to make a backup of its value. We do this so we can restore it to the original policy after the test finishes executing. This was done to solve the issues with custom principals being serialized back into the main AppDomain and failing to deseralize.

Thanks
Visual Studio Product Team

At least the workaround is simple enough.

February 23, 2009

Conflict Between TypeMock and Reporting

Filed under: .NET Development — dfbaskin @ 1:47 pm

When using a LocalReport object within a unit test where TypeMock Isolator was running, I got the error:

Microsoft.Reporting.WinForms.LocalProcessingException : An error occurred during local report processing.
  ----> Microsoft.ReportingServices.ReportProcessing.ReportProcessingException :
Failed to load expression host assembly.
Details: Operation could destabilize the runtime.

If TypeMock Isolator was disabled, the test ran correctly. This particular test was not using TypeMock calls at all. It was just the presence of the TypeMock Isolator engine that caused the error. I assumed that there was some conflict between TypeMock Isolator and the report processing engine.

This post, by Mohamed Sharaf, provided some clues as to what was causing the error. In the end, using the ExecuteReportInCurrentAppDomain method allowed the test to run correctly.

January 3, 2009

Windows Installer Patches using WiX

Filed under: WiX — Tags: , , — dfbaskin @ 9:35 pm

John Robbins posts very helpful information about cumulative patches using WiX. It fixed the problem I was having making subsequent patch files.

Heath Stewart also provides additional information about the MinorUpdateTargetRTM.

December 29, 2008

WorkflowServiceHost Limitations and Work-Arounds

Filed under: WorkFlow — Tags: , — dfbaskin @ 6:37 pm

The implementation of the WorkflowServiceHost class apparently requires a single instance of the class to be created for each type of workflow being hosted. This also means that a separate workflow runtime will be created for each of these instances. This doesn’t seem to be very efficient since a single workflow runtime can handle multiple types of workflows. Multiple workflow runtimes seem like a waste of resources.

So I asked around about this.

Kenn Scribner, author of Microsoft Windows Workflow Foundation Step by Step, answers:

The short answer is you are correct, and a lot of people aren’t happy about this limitation. I’ve heard rumors this might be corrected in .NET 4.0, but just rumors.

An alternative is to write your own host class, if you’re of a mind to do so…

Paul Mehner adds his thoughts:

I was not aware that send/receive activities require a new runtime and I am thinking that this is likely just a configuration issue. I assure you that you do not want multiple hosts no matter what. That would be a ridiculous constraint if it proved to be true, and I plan to investigate this later tonight if my time permits (it likely won’t but I will try). In general, you should have only one workflow runtime for a single AppDomain, and that runtime can easily service many types of workflows.

BTW: I completely avoid using the send/receive activities. In point of fact, I have _never_ used them in a production application (only for training and demo purposes). These activities couple a workflow with a need to be used in a service host, thus preventing a workflow from being used independent of its hosting environment. I like a better separation of concerns than this model allows. I also like business developers to stay focused on their own business implementations without worrying about the network plumbing that services developers are concerned with (who likewise don’t want to be burdened with having to understand business rules and processes). I _always_ create my own service host, which itself hosts a singleton of the WF runtime. I can then run an infinite number of differing workflow types based on the service operations that are called. I can provide additional sample code if you would like… just ask. Here’s a starter though…

   [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
   [ErrorHandlingServiceBehavior(typeof(EpukServiceErrorHandler))]
   public class EpukServiceBus : ServiceBase, IEpukServiceBus
   {
       public EpukServiceBus() : base()
       {
             Factory factory = new Factory();
             ....
       }

And later adds:

The workflow runtime is designed to support multiple workflow types running simultaneously. That’s a fact you can bank on. If the ReceiveActivity violates that principle by introducing a need for multiple workflow runtimes for each workflow type, then that product manager REALLY screwed things up. I still haven’t had time to prove or disprove that assertion, and I will be traveling from the holidays back home today (and with pass conditions in the PNW — likely tomorrow as well), so it’s not likely this week.

Is the workflow we are talking about a sequential workflow or a state machine? It sounds to me like this is a state machine workflow, so I think I would probably just drive it off of the events that cause the state changes. I would expose the state change events through the abstraction of different operations on my operation contract, and I would pass the data into the workflow through the corresponding custom EventArgs. An external caller would call an operation on the service that would raise the appropriate state transition event on the workflow, and pass in the relevant data. I have used this pattern on several production systems with great success. Of course a single operation on the service contract could examine the data and then raise the appropriate event (if that makes the interface simpler for the caller, like the facade pattern described below).

I dislike the entire concept of the Receive/Send activities. I find that they too often violate my sense of separation of concerns. If they are really wired with the limitations that people are blogging about, then I find them to be much worse than that.

This forum post also confirms the limitation.

I agree that there should be a good separation of concerns in a production implementation (as Paul discusses above). For a project that I am working on, I ended up defining workflow events but created a service layer that fires the events. This separates communications issues from the actual hosting of the workflow.

Another idea, suggested in the forums post above, was to create a single workflow with a number of receive activities that route incoming requests to other workflows (using the Facade pattern). This is an interesting idea as well, but I have not tried it.

December 27, 2008

Using IDisposable Objects in PowerShell

Filed under: Powershell — Tags: , , — dfbaskin @ 10:50 pm

In C#, you can easily dispose of objects by making use of the using statement, so long at the object implements the IDisposable interface.

So how do you do this in PowerShell? Fortunately, Adam Weigert and Keith Dahlby have done the hard work:

Thanks guys!

« Newer PostsOlder Posts »

Create a free website or blog at WordPress.com.