Pirates Video

by Cameron Albert 11. March 2010 12:22

Here is a video of the Pirates game:

General Purpose Sprite Class

by Cameron Albert 10. March 2010 23:09

On the heels of some great posts by Bill Reiss on Sprites Part 1 and Sprites Part 2 in Silverlight I wanted to post some general base sprite classes that I use. The classes are intended to be used with the SilverSprite framework.

These classes all exist in an assembly I lovingly call the “Shady Engine” (to explain the namespaces)

The base class I used is ingeniously called Sprite. It implements an interface called ISprite. I added the interface in order to create an interface called IPlayer that the main Game class uses.

ISprite.cs

using System.Windows;
using Microsoft.Xna.Framework;

namespace Shady.Sprites
{
    public interface ISprite
    {
        ISprite Owner { get; set; }
        Vector2 Position { get; set; }
        double Rotation { get; set; }
        System.Windows.Point Scale { get; set; }
        double Width { get; set; }
        double Height { get; set; }
        Rect Bounds { get; }
        bool IsActive { get; set; }
    }
}

And here is the Sprite.cs file:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Microsoft.Xna.Framework;

namespace Shady.Sprites
{
    [TemplatePart(Name = PART_RootElement, Type = typeof(Canvas))]
    [TemplatePart(Name = PART_ContentElement, Type = typeof(ContentControl))]
    [TemplatePart(Name = PART_DebugCenter, Type = typeof(Ellipse))]
    [ContentProperty("Content")]
    public class Sprite : Control, ISprite
    {
        public const string PART_RootElement = "PART_RootElement";
        public const string PART_ContentElement = "PART_ContentElement";
        public const string PART_DebugCenter = "PART_DebugCenter";

        protected Canvas RootElement { get; set; }
        protected ContentControl ContentElement { get; set; }
        protected Ellipse DebugCenterElement { get; set; }

        protected TranslateTransform TranslateTransform { get; set; }
        protected RotateTransform RotateTransform { get; set; }
        protected ScaleTransform ScaleTransform { get; set; }

        protected double HalfWidth = 0;
        protected double HalfHeight = 0;

        public ISprite Owner { get; set; }    

        public object Content
        {
            get { return (object)GetValue(ContentProperty); }
            set { SetValue(ContentProperty, value); }
        }
        public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(object), typeof(Sprite), new PropertyMetadata(null));

        public bool Debug
        {    
            get { return (bool)GetValue(DebugProperty); }
            set { SetValue(DebugProperty, value); }
        }
        public static readonly DependencyProperty DebugProperty = DependencyProperty.Register("Debug", typeof(bool), typeof(Sprite), new PropertyMetadata(false, new PropertyChangedCallback(Sprite.OnDebugPropertyChanged)));
        private static void OnDebugPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var sprite = obj as Sprite;
            if (sprite == null)
                return;

            if (sprite.DebugCenterElement != null)
                sprite.DebugCenterElement.Visibility = (bool)e.NewValue ? Visibility.Visible : Visibility.Collapsed;
        }
            
        public Vector2 Position    
        {
            get 
            { 
                var x = (double)GetValue(Canvas.LeftProperty);
                var y = (double)GetValue(Canvas.TopProperty);
                return new Vector2((float)x, (float)y); 
            }
            set
            {
                SetValue(Canvas.LeftProperty, (double)value.X);
                SetValue(Canvas.TopProperty, (double)value.Y);
            }
        }

        public virtual double Rotation
        {
            get { return this.RotateTransform.Angle; }
            set { this.RotateTransform.Angle = value; }
        }

        public System.Windows.Point Scale
        {
            get { return new System.Windows.Point(this.ScaleTransform.ScaleX, this.ScaleTransform.ScaleY); }
            set
            {
                this.ScaleTransform.ScaleX = value.X;
                this.ScaleTransform.ScaleY = value.Y;
            }
        }

        public new double Width
        {
            get { return base.Width; }
            set
            {
                base.Width = value;
                HalfWidth = Width * 0.5;
                TranslateTransform.X = -HalfWidth;
                if (this.DebugCenterElement != null)
                    Canvas.SetLeft(this.DebugCenterElement, HalfWidth);
            }
        }

        public new double Height
        {
            get { return base.Height; }
            set
            {
                base.Height = value;
                HalfHeight = Height * 0.5;
                TranslateTransform.Y = -HalfHeight;
                if (this.DebugCenterElement != null)
                    Canvas.SetTop(this.DebugCenterElement, HalfHeight);
            }
        }

        public Rect Bounds
        {
            get
            {
                Vector2 position = this.Position;
                return new Rect(position.X - HalfWidth, position.Y - HalfHeight, this.Width, this.Height);
            }
        }

        private WriteableBitmap _bitmap;
        protected internal virtual WriteableBitmap Bitmap
        {
            get
            {
                if (_bitmap == null && this.ContentElement != null)
                {
                    var content = this.ContentElement.Content;
                    if (content != null && content is Image)
                    {
                        _bitmap = new WriteableBitmap((int)this.Width, (int)this.Height);
                        _bitmap.Render((content as Image), new TranslateTransform());
                        _bitmap.Invalidate();
                    }
                }
                return _bitmap;
            }
        }

        private bool _isActive = true;
        public bool IsActive
        {
            get { return _isActive; }
            set
            {
                _isActive = value;
                this.Visibility = _isActive ? Visibility.Visible : Visibility.Collapsed;
            }
        }

        public Sprite()
        {
            this.DefaultStyleKey = typeof(Sprite);

            this.TranslateTransform = new TranslateTransform();
            this.RotateTransform = new RotateTransform();
            this.ScaleTransform = new ScaleTransform();
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            this.RootElement = GetTemplateChild(PART_RootElement) as Canvas;
            this.ContentElement = GetTemplateChild(PART_ContentElement) as ContentControl;
            this.DebugCenterElement = GetTemplateChild(PART_DebugCenter) as Ellipse;

            if (DebugCenterElement != null && !Double.IsNaN(this.Width) && !Double.IsNaN(this.Height))
            {
                Canvas.SetLeft(DebugCenterElement, HalfWidth - 1.5);
                Canvas.SetTop(DebugCenterElement, HalfHeight - 1.5);
            }

            if (this.RootElement != null)
            {
                var group = new TransformGroup();
                group.Children.Add(TranslateTransform);
                group.Children.Add(RotateTransform);
                group.Children.Add(ScaleTransform);

                this.RootElement.RenderTransform = group;
                this.RootElement.RenderTransformOrigin = new System.Windows.Point(0, 0); // At 0,0 because the translate transform positions the sprite.
            }

            this.Initialize();
        }

        public virtual void Initialize()
        {
        }

        public virtual void Update(GameTime gameTime)
        {
        }

        public virtual void Draw(GameTime gameTime)
        {
        }

        /// <summary>
        /// Re-initializes the sprite.
        /// </summary>
        public virtual void Reset()
        {
            this.IsActive = true;
            this.Owner = null;
        }

        protected static void OnDependencyPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var sprite = obj as Sprite;
            if (sprite == null) return;
            sprite.Initialize();
        }
    }
}

Because Sprite is a templated control there is also some XAML to go along with it (You will need to place this in a themes/generic.xaml file):

<Style TargetType="sprites:Sprite">
        <Setter Property="Background" Value="{x:Null}"></Setter>
        <Setter Property="Foreground" Value="{x:Null}"></Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="sprites:Sprite">
                    <Canvas x:Name="PART_RootElement" Background="{TemplateBinding Background}">
                        <ContentControl x:Name="PART_ContentElement"/>
                        <Ellipse x:Name="PART_DebugCenter" Width="3" Height="3" Fill="Red" Visibility="Collapsed"/>
                    </Canvas>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

That is my basic Sprite class, I will post my animated sprite class next.

Tags: , , , ,

Silverlight Games | Silverlight | Game Development | General

Yar, I do be re-visiting Pirates!

by Cameron Albert 10. March 2010 13:03

One of the first games I started building in Silverlight I called Pirates! Since working on Perenthia and various other tasks I have not re-visited the game for a long time. I really would like to get this game finished so I have to decided to spend some time working on it. I hope to include some videos soon that show the game in varied stages of development. The first screen shot displays what currently exists after implementing some path finding and the SilverSprite library:

Here is the post from the game blog: Pirates Game in Silverlight

XNA and Silverlight Development

by Cameron Albert 1. February 2010 13:57

Mad Laumann has a new post up about the development progress of his game Little Longhorn, a tower defense game written for XNA and Silverlight using the SilverSprite framework. I have been following his progress with the game and have been able to play the early versions of it (both XNA and Silverlight) and have found it quite fun and challenging. The game has grown quite a bit over the last few months with game play and graphics improving all the time. Needless to say Mads is becoming an authority on XNA/Silverlight combination platform development so be sure to check out his blog A Silverlight Playground.

Tags: , , ,

Game Development | General | Silverlight | Silverlight Games

Silverlight 4 Business Application Development – Beginner’s Guide

by Cameron Albert 18. January 2010 19:47

For those of you out there wanting to get into Silverlight development but just do not know where to start, Frank LaVigne and I have just about completed our book titled Microsoft Silverlight 4 Business Application Development – Beginner’s Guide(link to pre-order). This book will be ideal for current Windows or ASP.NET developers who want to learn Silverlight and because the book is centered on Business Application Development we will empower you with knowledge so you can recommend Silverlight for the next business project at your company.

Gaining the basics required to develop in Silverlight, make use of data binding, WCF and RIA Services you will be prepared to lead the Silverlight charge at your company. Be warned, once you start developing in Silverlight you will have a hard time going back to normal ASP.NET development.

Tags:

General | Silverlight | Silverlight Business Development

Silverlight Tile Map using WriteableBitmap

by Cameron Albert 23. November 2009 12:52

Bill Reiss posted an interesting article and code the other day concerning the WriteableBitmap class and some extension methods. I downloaded the code and wrote a tiling map control using the WriteableBitmap class for my multi-player role playing game. Here is a snippet of the important piece of code that does the rendering:

   1:  private void RenderMap()
   2:  {
   3:      var xPos = _center.X - _halfX;
   4:      var yPos = _center.Y - _halfY;
   5:   
   6:      for (int y = 0; y < _numTilesY; y++)
   7:      {
   8:          for (int x = 0; x < _numTilesX; x++)
   9:          {
  10:              var tile = _tiles[new Point3(xPos, yPos, _zIndex)];
  11:              var terrain = Game.Terrain.Where(t => t.ID == tile.Terrain).FirstOrDefault();
  12:              if (terrain == null)
  13:                  terrain = Game.GetDefaultTerrain();
  14:   
  15:              _surface.Blit(new Point(x * TileWidth, y * TileHeight), 
  16:                  _tileImage, 
  17:                  _tileRect, 
  18:                  terrain.GetColor(), 
  19:                  BlendMode.AlphaBlend);
  20:              xPos++;
  21:          }
  22:          xPos = _center.X - _halfX;
  23:          yPos++;
  24:      }
  25:   
  26:      _surface.Invalidate();
  27:  }

The _surface variable is just a WriteableBitmap instance initialized to the width and height of the map control. The _tiles variable holds a list of the map tiles in range of the _center position. The xPos and yPos are the world coordinates and the terrain instance just holds the color to paint the tile.

The end result looks something like this:

perenthia tile map

Tags: , ,

Game Development | General | Perenthia PBBG | Silverlight Games

Silverlight and Multi-Player Games

by Cameron Albert 9. August 2009 20:31

I have been working on a multi-player library for Silverlight games over the past few months, well, off and on working on it while continuing Perenthia development.

I hope to be able to get the code on CodePlex before too much longer along with a tutorial on how to use it and a demo game.

The library will start with Duplex services but I do have plans to implement sockets in the future. Silverlight’s duplex and socket support is sufficient for RPGs and RTS or really any kind of turn based game but until Silverlight can support UDP sockets it is probably not suited to real time action games.

The goal is that the library can be used with any game engine such as SilverSprite or PlayBits and that it will provide easy to setup and use networking capabilities for your game.

The library is coming along well and I am building a demo game to help with implementation and testing that I hope to have finished in the next week or so.

Game Objects - My Design

by Cameron Albert 15. May 2009 18:34

I thought I would share one of the core concepts I implemented in Perenthia that has been working quite well. Early on in development I decided to create templates and instances in regards to game objects. A template would define common, unchangable properties of an object whereas an instance would be the opposite. An example would be a Sword; there is a template for a Sword that defines its damage value, price, required skill level, etc. 

I have one table that stores all the objects for the game. Since objects being actively used are loaded into memory and the table is indexed for those queries it runs pretty fast. Since I store all of the objects into one table I make heavy use of the XML data type in SQL 2005 to provide a bunch of XML Serialized Key/Value pairs that define the properties of an object. On the code side of things a dictionary provides the underlying data store for properties of the object. For instance, the Sword example above has a Power property that is used in combination with the wielder's skill in swords to determine damage. The Power property just fetches the Power value from the properties dictionary using the property name. This works a lot like the dependency properties, just my collection serializes to XML for database storage. When an object is loaded from the database the xml from the template is retrieved and added to the object, then the object instance xml is dropped into the object, overriding any template properties of the same name.

This property dictionary also allows me to store whether or not the property belongs to a template or instance. If the property belongs to a template then when the instance is serialized and saved to the database those template properties are excluded. Likewise saving a template does not serialize and save the instance properties. This structure allows for a lot of flexibility with my objects and has been working out quite well. I probably would not have used serialization and xml the way I am if I was doing a typical call to the database qith each request as the extra overhead would not have been worth the effort. However, since my objects are loaded into memory and my saves are background threaded I experience a lot of benefit of an easy to use object.

I shuld note that players character data is stored in a separate table from the core objects table. It follows the same design buy allows me to migrate and change data in the objects table without overwriting player data, since players are essentially the same as mobiles. 

Perenthia World Builder in Silverlight

by Cameron Albert 29. April 2009 00:01

I have been working to modify the tool I wrote for building the Perenthia world. The tool started life as a WinForms application, migrated to a WPF application but is now a part of the Silverlight Client UI. Since all of the actions are role based and controlled with permission on the server having it in the main client UI allows me to make use of all of the framework already in place for Perenthia.

The world builder UI connects to the server via WCF services tailored for world building. What this will also give me is the ability to open up the world builder to allow users to create custom dungeons, towns, etc.

Some features of the world builder are a background map of the world so I know where to place rooms, zoom capabilities that scale the map, draggable map and the ability to drag items, creatures, NPCs, etc. onto rooms on the map and configure the properties of each.

Silverlight Window Control

by Cameron Albert 22. April 2009 17:08

Here is a draggable Window control I wrote in Silverlight for Perenthia. A screen shot of the Window being used can be seen at http://cameronalbert.com/post/2008/11/19/Silverlight-Game-Controls.aspx

Here is the XAML from my generics.xaml file:

 

<!-- Default style for Lionsguard.Window -->
	<Style TargetType="lg:Window">
		<Setter Property="Background" Value="#99000000" />
		<Setter Property="Foreground" Value="#FFFFFFFF" />
		<Setter Property="BorderBrush" Value="#FFC38312" />
		<Setter Property="Template">
			<Setter.Value>
				<ControlTemplate TargetType="lg:Window">
					<Grid x:Name="RootElement">
						<Border HorizontalAlignment="Stretch" Margin="0,24,0,0" Padding="4,4,4,4" VerticalAlignment="Stretch" BorderThickness="2,2,2,2" CornerRadius="0,0,4,4">
							<ContentControl x:Name="ContentElement" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"/>
						</Border>
						<Border Height="24" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Top" CornerRadius="4,4,0,0" BorderThickness="2,2,2,0" x:Name="TitleBarElement" />
						<Button Height="20" HorizontalAlignment="Right" Margin="0,3,3,0" VerticalAlignment="Top" Width="20" Content="X" FontWeight="Bold" FontFamily="Trebuchet MS" FontSize="14" x:Name="CloseButtonElement"/>
						<TextBlock Height="20" Margin="8,3,27,0" VerticalAlignment="Top" Text="Title" TextWrapping="Wrap" x:Name="TitleLabelElement" FontFamily="Georgia" FontSize="16" FontWeight="Bold" HorizontalAlignment="Left"/>
					</Grid>
				</ControlTemplate>
			</Setter.Value>
		</Setter>
	</Style>

 

And here is the code for the class:

 

using System;
using System.Collections.Generic;
using System.Net;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Lionsguard
{
	[TemplatePart(Name = "RootElement", Type = typeof(FrameworkElement))]
	[TemplatePart(Name = "ContentElement", Type = typeof(ContentControl))]
	[TemplatePart(Name = "TitleBarElement", Type = typeof(Border))]
	[TemplatePart(Name = "CloseButtonElement", Type = typeof(Button))]
	[TemplatePart(Name = "TitleLabelElement", Type = typeof(TextBlock))]
	[ContentProperty("Content")]
	public class Window : Control
	{
		public FrameworkElement RootElement { get; set; }
		private ContentControl ContentElement { get; set; }
		private Border TitleBarElement { get; set; }
		private Button CloseButtonElement { get; set; }
		private TextBlock TitleLabelElement { get; set; }

		private Point MousePosition { get; set; }

		/// <summary>
		/// Gets or sets the Content of the Window.
		/// </summary>
		public UIElement Content
		{
			get { return (UIElement)GetValue(ContentProperty); }
			set { SetValue(ContentProperty, value); }
		}
		public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(UIElement), typeof(Window), new PropertyMetadata(null, new PropertyChangedCallback(Window.OnContentPropertyChanged)));
		private static void OnContentPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
		{
			(obj as Window).SetControlValues();
		}

		/// <summary>
		/// Gets or sets the Title displayed in the title bar of the window.
		/// </summary>
		public string Title
		{
			get { return (string)GetValue(TitleProperty); }
			set { SetValue(TitleProperty, value); }
		}
		public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(Window), new PropertyMetadata("Title", new PropertyChangedCallback(Window.OnTitlePropertyChanged)));
		private static void OnTitlePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
		{
			(obj as Window).SetControlValues();
		}

		/// <summary>
		/// Gets or sets a value indicating whether or not the close button of the title bar should be displayed.
		/// </summary>
		public bool ShowCloseButton
		{
			get { return (bool)GetValue(ShowCloseButtonProperty); }
			set { SetValue(ShowCloseButtonProperty, value); }	
		}
		public static readonly DependencyProperty ShowCloseButtonProperty = DependencyProperty.Register("ShowCloseButton", typeof(bool), typeof(Window), new PropertyMetadata(true, new PropertyChangedCallback(Window.OnShowCloseButtonPropertyChanged)));
		private static void OnShowCloseButtonPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
		{
			(obj as Window).SetControlValues();
		}

		/// <summary>
		/// Gets a value indicating whether or not the window is currently open and visible.
		/// </summary>
		public bool IsOpen
		{
			get { return this.Visibility == Visibility.Visible; }
		}

		/// <summary>
		/// An event that is raised when the window is closed.
		/// </summary>
		public event EventHandler Closed = delegate { };

		/// <summary>
		/// Initializes a new instance of the Lionsguard.Window class.
		/// </summary>
		public Window()
		{
			this.DefaultStyleKey = typeof(Window);
		}

		public override void OnApplyTemplate()
		{
			base.OnApplyTemplate();

			this.RootElement = base.GetTemplateChild("RootElement") as FrameworkElement;
			this.ContentElement = base.GetTemplateChild("ContentElement") as ContentControl;
			this.TitleBarElement = base.GetTemplateChild("TitleBarElement") as Border;
			this.CloseButtonElement = base.GetTemplateChild("CloseButtonElement") as Button;
			this.TitleLabelElement = base.GetTemplateChild("TitleLabelElement") as TextBlock;
			
			if (this.RootElement != null)
			{
				this.RootElement.MouseLeftButtonDown += new MouseButtonEventHandler(OnRootElementMouseLeftButtonDown);

				this.TitleBarElement.MouseLeftButtonDown += new MouseButtonEventHandler(OnTitleBarMouseLeftButtonDown);
				this.TitleBarElement.MouseEnter += new MouseEventHandler(OnTitleBarMouseEnter);
				this.TitleBarElement.MouseLeave += new MouseEventHandler(OnTitleBarMouseLeave);

				this.TitleLabelElement.MouseLeftButtonDown += new MouseButtonEventHandler(OnTitleBarMouseLeftButtonDown);
				this.TitleLabelElement.MouseEnter += new MouseEventHandler(OnTitleBarMouseEnter);
				this.TitleLabelElement.MouseLeave += new MouseEventHandler(OnTitleBarMouseLeave);

				this.CloseButtonElement.Click += new RoutedEventHandler(OnCloseButtonClick);

				this.SetControlValues();
			}
		}

		private void SetControlValues()
		{
			if (this.ContentElement != null && this.Content != null)
			{
				this.ContentElement.Content = this.Content;
			}
			if (this.TitleLabelElement != null)
			{
				this.TitleLabelElement.Text = this.Title;
				ToolTipService.SetToolTip(this.TitleLabelElement, this.Title);
			}
			if (this.CloseButtonElement != null)
			{
				if (this.ShowCloseButton) this.CloseButtonElement.Visibility = Visibility.Visible;
				else this.CloseButtonElement.Visibility = Visibility.Collapsed;
			}
		}

		private void OnRootElementMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
		{
			// Set the Z-Index of the window to the top most position.
			this.BringToFront();
		}

		private void OnCloseButtonClick(object sender, RoutedEventArgs e)
		{
			this.Close();
		}

		private void OnTitleBarMouseLeave(object sender, MouseEventArgs e)
		{
			this.Cursor = Cursors.Arrow;
		}

		private void OnTitleBarMouseEnter(object sender, MouseEventArgs e)
		{
			this.Cursor = Cursors.Hand;
		}

		private void OnTitleBarMouseMove(object sender, MouseEventArgs e)
		{
			Point position = e.GetPosition(null);

			// Prevent the mouse from moving outside the bounds of the parent canvas.
			if (position.X <= 30) position.X = 30;
			if (position.Y <= 30) position.Y = 30;

			Canvas parent = this.Parent as Canvas;
			if (parent != null)
			{
				if (position.X >= (parent.Width - 30)) position.X = parent.Width - 30;
				if (position.Y >= (parent.Height - 30)) position.Y = parent.Height - 30;
			}

			System.Diagnostics.Debug.WriteLine("position = {0}", position);

			double deltaX = position.X - this.MousePosition.X;
			double deltaY = position.Y - this.MousePosition.Y;
			
			Point newPosition = new Point(
				((double)this.GetValue(Canvas.LeftProperty)) + deltaX,
				((double)this.GetValue(Canvas.TopProperty)) + deltaY);

			this.SetValue(Canvas.LeftProperty, newPosition.X);
			this.SetValue(Canvas.TopProperty, newPosition.Y);

			this.MousePosition = position;
		}

		private void OnTitleBarMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
		{
			((UIElement)sender).ReleaseMouseCapture();

			this.Cursor = Cursors.Arrow;

			this.TitleBarElement.MouseLeftButtonUp -= new MouseButtonEventHandler(OnTitleBarMouseLeftButtonUp);
			this.TitleBarElement.MouseMove -= new MouseEventHandler(OnTitleBarMouseMove);
			this.TitleLabelElement.MouseLeftButtonUp -= new MouseButtonEventHandler(OnTitleBarMouseLeftButtonUp);
			this.TitleLabelElement.MouseMove -= new MouseEventHandler(OnTitleBarMouseMove);
		}

		private void OnTitleBarMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
		{
			this.MousePosition = e.GetPosition(null);
			this.Cursor = Cursors.Hand;

			((UIElement)sender).CaptureMouse();

			this.TitleBarElement.MouseLeftButtonUp += new MouseButtonEventHandler(OnTitleBarMouseLeftButtonUp);
			this.TitleBarElement.MouseMove += new MouseEventHandler(OnTitleBarMouseMove);
			this.TitleLabelElement.MouseLeftButtonUp += new MouseButtonEventHandler(OnTitleBarMouseLeftButtonUp);
			this.TitleLabelElement.MouseMove += new MouseEventHandler(OnTitleBarMouseMove);
		}

		/// <summary>
		/// Causes the current window to be re-z-indexed to the top most window.
		/// </summary>
		protected void BringToFront()
		{
			// Search the top most "Window" and swap z-indexes.
			Panel parent = this.Parent as Panel; // Panel is the base for Canvas, Grid and StackPanel.
			if (parent != null)
			{
				int currentZIndex = (int)this.GetValue(Canvas.ZIndexProperty);
				var child = (from c in parent.Children where c is Window select c as Window).OrderByDescending(c => (int)c.GetValue(Canvas.ZIndexProperty)).FirstOrDefault();
				if (child != null)
				{
					int topZIndex = (int)child.GetValue(Canvas.ZIndexProperty);
					if (topZIndex == 0) topZIndex = 1; // If the value has not been set then just default it to 1.
					if (topZIndex > currentZIndex)
					{
						this.SetValue(Canvas.ZIndexProperty, topZIndex);
						child.SetValue(Canvas.ZIndexProperty, currentZIndex);
					}
				}
			}
		}

		public void Show()
		{
			this.Visibility = Visibility.Visible;
			// If content is present show that as well.
			if (this.Content != null) this.Content.Visibility = Visibility.Visible;
		}

		public void Close()
		{
			this.Visibility = Visibility.Collapsed;
			// If content is present hide that as well.
			if (this.Content != null) this.Content.Visibility = Visibility.Collapsed;
			this.Closed(this, EventArgs.Empty);
		}

		public void ToggleWindow()
		{
			if (this.Visibility == Visibility.Visible)
			{
				this.Close();
			}
			else
			{
				this.Show();
			}
		}
	}
}

 

This is how I am using it within the Pernethia UI (The content of window is actually the Character Sheet as displayed in the screenshot from above):

Namespace: xmlns:Lionsguard="clr-namespace:Lionsguard;assembly=Lionsguard.Silverlight"

 

<Lionsguard:Window Height="375" x:Name="diagCharacterSheet" Visibility="Collapsed" Width="634" Canvas.Left="8" Canvas.Top="19" Title="Character Sheet" Style="{StaticResource WindowStyle}" d:IsLocked="True">
    		<Perenthia_Dialogs:CharacterSheetDialog x:Name="diagCharacterSheetContent" SkillChanged="diagCharacterSheetContent_SkillChanged"/>
		</Lionsguard:Window>

 

Enjoy!

 

Powered by BlogEngine.NET 1.5.0.7
Modified Theme by Mads Kristensen

About the Author

CameronAlbert.com I am Senior Software Development Consultant specializing in Silverlight, WPF and the Microsoft .NET Framework. 

My current project Perenthia is a Silverlight multi-player game based in a fantasy world that combines text adventure games with some moderate graphics

View Cameron Albert's profile on LinkedIn
See how we're connected

Follow cameronalbert on Twitter

 

Recommended Books

Silverlight 4 Business Application Development - Beginner's Guide:

http://www.packtpub.com/microsoft-silverlight-4-business-application-development-beginners-guide/book

Microsoft Silverlight 4 Business Application Development: Beginner’s Guide