Blog

posts tagged with silverlight

Porting Sudoku to Windows Phone 7

0 Comments
By Fons Sonnemans, 4-7-2010

Last year I wrote a Sudoku using Silverlight 2. I'm now porting it to the Windows Phone 7. I started designing the UX. I decided to stick to the Metro design. It's really clean.

I'm using the ApplicationBar and Menu. I'm not totally sure which buttons to use. For now: pause, undo, redo and hint. I will have to create a ShakeTrigger which I will use to create a new game. I will have to postpone this until I have a real device to develop on. The accelerometer is hard to emulate.

I'm also planning to 'import' Sudoku's using the phone camera and OCR. But probably not in the first version.

I hope to show you a working version in a YouTube video soon. Come back later. All feedback is welcome on fons@reflectionit.nl

Cheers,

Fons

SpiralText in Silverlight 4

0 Comments
By Fons Sonnemans, 31-5-2010

Blend 4.0 includes a new PathListBox control. In Silverlight 4 you can create your own shapes by deriving from the Path class. I have used these two techniques to create this SpiralText sample.

The Spiral class uses ArcSegment objects to create a spiral illusion. It isn't a perfect spiral but it is good enough for me.

The LayoutPath of the PathListBox is set to the Spiral. The ItemsSource is databound to the TextBox.

You can also select the Font, Color, Font Size, Font Spacing and the number of Spirals.

Get Microsoft Silverlight

The Spiral class was all the code I hade to write. Everything else is done using XAML. You can download the sourcecode from here

Cheers,

Fons

RightMouseTrigger

0 Comments
By Fons Sonnemans, 9-5-2010

I have written a Silverlight Minesweepe game in October 2008. I just published an improved version on Silver Arcade which support right mouse click. I implemented it using the following RightMouseTrigger. You can set the SetHandled property to true. This stops the MouseRightButtonDown event from bubbling to it's parent.

I really love Behaviors, Actions and Triggers. I hope you like it too.

public class RightMouseTrigger : EventTriggerBase<Control> {


    protected override string GetEventName() {

        return "MouseRightButtonDown";

    }


    #region SetHandled Dependency Property


    /// <summary>

    /// Get or Sets the SetHandled dependency property. 

    /// </summary>

    public bool SetHandled {

        get { return (bool)GetValue(SetHandledProperty); }

        set { SetValue(SetHandledProperty, value); }

    }


    /// <summary>

    /// Identifies the SetHandled dependency property.

    /// This enables animation, styling, binding, etc...

    /// </summary>

    public static readonly DependencyProperty SetHandledProperty =

        DependencyProperty.Register("SetHandled",

                                    typeof(bool),

                                    typeof(RightMouseTrigger),

                                    new PropertyMetadata(true));


    #endregion SetHandled Dependency Property


    protected override void OnEvent(EventArgs eventArgs) {

        var ea = eventArgs as MouseButtonEventArgs;

        if (ea != null && SetHandled) {

            ea.Handled = true;

        }

        base.OnEvent(eventArgs);

    }


}

CountDown Clock in Silverlight 4

0 Comments
By Fons Sonnemans, 1-4-2010

A while ago I wrote a FlipClock Silverlight 3 application. I have modified it into a CountDown Clock which you can configure using InitParams. It is written in Silverlight 4 and uses the new Viewbox control to make it scalable. I hope you like it.

You can download the sourcecode from here.

Get Microsoft Silverlight

<object data="data:application/x-silverlight-2," type="application/x-silverlight-2"

    width="400" height="200">

    <param name="source" value="ClientBin/ReflectionIT.Silverlight.CountDown.xap" />

    <param name="initParams" value="title=Silverlight 4 RTW,date=2010-04-13 08:00AM-8:00" />

    <param name="background" value="white" />

    <param name="minRuntimeVersion" value="4.0.50303.0" />

    <param name="autoUpgrade" value="true" />

    <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.41108.0" style="text-decoration: none">

        <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight"

            style="border-style: none" />

    </a>

</object>

 

Get Microsoft Silverlight

<param name="initParams" value="title=New Year,date=2012-1-1" />

DevDays 2010 Materiaal

0 Comments
By Fons Sonnemans, 1-4-2010

Zoals beloofd kan je de Presentatie + Demo's van mijn 'Introduction to WCF RIA Services' sessie van de DevDays downloaden. Je dient eerst wel de Northwind database te installeren op localhost\SQLEXPRESS. Het benodigde installatiescript is ook in de ZIP file opgenomen. 

Mijn WCF RIA Services sessie op DevDays 2010

0 Comments
By Fons Sonnemans, 17-2-2010

Op 30 en 31 maart a.s. vinden de Microsoft Development Days (DevDays) plaats. DevDays is een evenement dat al 13 jaar dé bron van kennis en inspiratie voor IT ontwikkelaars is. Ook deze keer vinden de DevDays plaats in het World Forum in Den Haag.

Dit jaar zijn de DevDays voor mij extra speciaal omdat ik door Microsoft ben gevraagd om als spreker op de DevDays te verschijnen. Op dinsdag 30 maart mag ik een sessies verzorgen over een onderdeel van Silverlight 4, namelijk WCF RIA Services. Met een goed doordacht Framework, op basis van codegeneratie, wordt hiermee het bouwen van gedistribueerde Silverlight applicaties veel eenvoudiger.

Wilt u ook naar mijn sessie komen luisteren, maar heeft u zich nog niet ingeschreven, ga dan naar www.devdays.nl, want ook u bent uiteraard van harte welkom.

Keyboard selection on Silverlight ListBox and ComboBox

3 Comments
By Fons Sonnemans, 7-2-2010

Silverlight doesn't support keyboard selection on a ListBox or Combox. I have created a small Behavior which fixes this problem. You can attach the KeyboardSelectionBehavior to a ListBox or ComboBox using Microsoft Expression Blend. You drag it from the Assets and drop it on your ComboBox or ListBox. If you have a custom ItemTemplate you will have to set the SelectionMemberPath property.

Try my behavior below. If you press a key on the ComboBox or ListBoxes it will select the next item starting with the given key.

Get Microsoft Silverlight

The ComboBox in this example is not databound, The behavior uses the Convert.ToString() method to convert the Content of each ListBoxItem/ComboBoxItem to a string. An invariant case insensitive StartWith() comparison is used to find the next item.

The left ListBox is databound to SampleData containing Employees. The behavior uses the DisplayMemberPath of the ListBox. The Name of the databound Employee is used for keyboard selection.

<ListBox Margin="79,64,0,23" DisplayMemberPath="Name"

    ItemsSource="{Binding Employees}" HorizontalAlignment="Left" Width="176">

    <i:Interaction.Behaviors>

        <local:KeyboardSelectionBehavior />

    </i:Interaction.Behaviors>

</ListBox>

The right ListBox is also databound but has a custom ItemTemplate. We can't use the DisplayMemberPath. The behavior has a SelectionMemberPath property to specify which property to use for selection. In this example it is set to the Name of the databound Employee.

<ListBox Margin="272,23,23,23"

    ItemsSource="{Binding Employees}">

    <i:Interaction.Behaviors>

        <local:KeyboardSelectionBehavior SelectionMemberPath="Name"/>

    </i:Interaction.Behaviors>

    <ListBox.ItemTemplate>

        <DataTemplate>

            <StackPanel Orientation="Horizontal">

                <Image Source="{Binding Image}" Height="32" Width="32"/>

                <StackPanel>

                    <TextBlock Text="{Binding Name}" FontWeight="Bold"/>

                    <TextBlock Text="{Binding Description}"/>

                </StackPanel>

            </StackPanel>

        </DataTemplate>

    </ListBox.ItemTemplate>

</ListBox>

Here is the code:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Controls.Primitives;

using System.Windows.Data;

using System.Windows.Input;

using System.Windows.Interactivity;

 

namespace ReflectionIT.Silverlight.Behaviors {

 

    ///<summary>

    /// This behavior can be attached to a ListBox or ComboBox to

    /// add keyboard selection

    ///</summary>

    public class KeyboardSelectionBehavior : Behavior<Selector> {

 

        ///<summary>

        /// Gets or sets the Path used to select the text

        ///</summary>

        public string SelectionMemberPath { get; set; }

 

        public KeyboardSelectionBehavior() {}

 

        ///<summary>

        /// Attaches to the specified object: subscribe on KeyDown event

        ///</summary>

        protected override void OnAttached() {

            base.OnAttached();

            this.AssociatedObject.KeyDown += DoKeyDown;

        }

 

        void DoKeyDown(object sender, KeyEventArgs e) {

 

            // Create a list of strings and indexes

            int index = 0;

            IEnumerable<Item> list = null;

            var path = SelectionMemberPath ??

                this.AssociatedObject.DisplayMemberPath;

            var evaluator = new BindingEvaluator();

            if (path != null) {

                list = this.AssociatedObject.Items.OfType<object>()

                    .Select(item => {

                        // retrieve the value using the supplied Path

                        var binding = new Binding();

                        binding.Path = new PropertyPath(path);

                        binding.Source = item;

 

                        BindingOperations.SetBinding(evaluator,

                            BindingEvaluator.TargetProperty, binding);

                        var value = evaluator.Target;

 

                        return new Item { Index = index++,

                                Text = Convert.ToString(value) };

                    });

            } else {

                list = this.AssociatedObject.Items.OfType<ListBoxItem>()

                    .Select(item => new Item { Index = index++,

                                Text = Convert.ToString(item.Content) });

            }

            // Sort the list starting at next selectedIndex to the end and

            // then from the beginning

            list = list.OrderBy(item => item.Index <=

                this.AssociatedObject.SelectedIndex ?

                item.Index + this.AssociatedObject.Items.Count : item.Index);

 

            // Find first starting with

            var text = e.Key.ToString();

            var first = list.FirstOrDefault(item => item.Text.StartsWith(text,

                StringComparison.InvariantCultureIgnoreCase));

            if (first != null) {

                // found

                this.AssociatedObject.SelectedIndex = first.Index;

            }

        }

 

        ///<summary>

        /// Helper class

        ///</summary>

        private class Item {

            public int Index;

            public string Text;

        }

 

        ///<summary>

        /// Helper class used for property path value retrieval

        ///</summary>

        private class BindingEvaluator : FrameworkElement {

 

            public static readonly DependencyProperty TargetProperty =

                DependencyProperty.Register(

                    "Target",

                    typeof(object),

                    typeof(BindingEvaluator), null);

 

            public object Target {

                get { return GetValue(TargetProperty); }

                set { SetValue(TargetProperty, value); }

            }

        }

 

    }

}

Updated 1-feb-2011

Sudeept Malik send me an email with some code changes which now makes it possible to use the keyboard in an open ComboBox.

You can download the code including the sample application here.

Silverlight Behaviors and Commands

0 Comments
By Fons Sonnemans, 21-12-2009

A few months ago I wrote an blog post about a Silverlight 3.0 LetItSnowBehavior. This Behavior can be used to add a Snow effect to a Canvas. Very usefull if you want to create a christmas card.

This behavior was always showing you falling snow flakes. You couldn't stop and (re)start the gameloop. The best way to implement this is by adding Commands to the behavior. This allows you to select one or more triggers to Start or Stop the gameloop. I have added the Start and Stop properties of the type ICommand to the LetItSnowBehavior class. In the constructor I have initialized these properties with new ActionCommand objects (Microsoft.Expression.Interactions.dll) and delegates to the OnStop() and OnStart() methods. Triggers attached to these commands will execute the these methods.

public class LetItSnowBehavior : Behavior<Canvas> {

 

    private DispatcherTimer _gameLoop = new DispatcherTimer();

 

    public LetItSnowBehavior() {

        // Create Commands

        this.Start = new ActionCommand(this.OnStart);

        this.Stop = new ActionCommand(this.OnStop);

 

        // Init timer

        _gameLoop.Interval = new TimeSpan(0, 0, 0, 0, 10);

        _gameLoop.Tick += new EventHandler(gameLoop_Tick);

        _gameLoop.Start();

    }

 

    public ICommand Start { get; private set; }

 

    public ICommand Stop { get; private set; }

 

    private void OnStart() {

        _gameLoop.Start();

    }

 

    private void OnStop() {

        _gameLoop.Stop();

    }

 

    ...

You can use Expression Blend to attach triggers to the Commands. Select the LetItSnowBehavior object and open it properties. Click the + button for the Start property and select an EventTrigger. Select the 'buttonStart' as source and the 'Click' as event. You can even add multiple triggers to the command.

Set Triggers on LetItSnowBehavior in Expression Blend 3.0

You can download the code from here.

Watch my Silverlight Christmas card

0 Comments
By Fons Sonnemans, 20-12-2009

Click the following image to see my Christmas card which I have created using Silverlight 3.0 and Expression Blend.

Click to view this Christmas card

I didn't have to write any line of  C# code. I only re-used some of my existing behaviors: LetItSnowBehavior and ControlMediaElementAction.

Tags: XAML, Silverlight

Simple ReportDocument for Silverlight 4

0 Comments
By Fons Sonnemans, 25-11-2009

I have written an Simple Report Library for Windows Forms applications a few years ago. The new Printing API makes it possible to create a similar solution for Silverlight 4.

You create a report by instantiating a new ReportDocument object. You can set the Title and the SubTitle. Next you add Paragraphs (FrameworkElements) to the report. Finally you Print the report.

ReportDocument r = new ReportDocument() {

    Title = "Test Title",

    SubTitle = "Test SubTitle",

};


for (int i = 0; i < 40; i++) {


    var tb = new TextBlock() {

        Text = "Test text " + i,

        FontSize = i + 10,

    };


    r.Paragraphs.Add(tb);

}


r.Print();

This prints the following Test Title.pdf if you print it to a PDF writer.

Test Title.pdf

The real magic is in the dp_PrintPage event handler of the ReportDocument class. The Header and the Paragraphs are added to a StackPanel. Before a paragraph is added the height (actual or the measured desired) is compared with the available space. If it doesn't fit the page is full and ready to be printed. The PageVisual is set to the StackPanel. The next page will continue with the current paragraph.

private void pd_PrintPage(object sender, PrintPageEventArgs e) {

    PageNumber++;

    if (_panel.Children.Count == 0) {

        _panel.Children.Add(Header);

    } else {

        // remove all except header

        while (_panel.Children.Count > 1) {

            _panel.Children.RemoveAt(1);

        }

    }

    _visual.Height = e.PrintableArea.Height;

    _visual.Width = e.PrintableArea.Width;


    double totalHeight = e.PrintableArea.Height - this.Margin.Top - this.Margin.Bottom;

    double totalWidth = e.PrintableArea.Width - this.Margin.Left - this.Margin.Right;


    double height;

    if (_header.ActualHeight > 0) {

        height = Header.ActualHeight;

    } else {

        Header.Measure(new Size(totalWidth, totalHeight));

        height = Header.DesiredSize.Height;

    }


    while (_currentParagraphIndex < Paragraphs.Count) {

        var paragraph = Paragraphs[_currentParagraphIndex];

        if (paragraph.ActualHeight > 0) {

            height += paragraph.ActualHeight;

        } else {

            var size = new Size(totalWidth, totalHeight - height);

            paragraph.Measure(size);

            height += paragraph.DesiredSize.Height;

        }

        if (height > totalHeight) {

            // doesn't fit anymore

            break;

        }

        _currentParagraphIndex++;

        _panel.Children.Add(paragraph);

    }


    e.PageVisual = _visual;

    e.HasMorePages = _currentParagraphIndex < Paragraphs.Count;

}

I hope you like it. I will discuss creating custom headers in a next post. You can download the code from Codeplex.

All postings/content on this blog are provided "AS IS" with no warranties, and confer no rights. All entries in this blog are my opinion and don't necessarily reflect the opinion of my employer or sponsors. The content on this site is licensed under a Creative Commons Attribution By license.