Jan 312010
 

Recently someone asked me to write a TicTacToe game. So I worked out a rough logic for it. Heres the code. The idea is that the computer first scans through the tic-tac-toe board for any winning positions available. If none are available, then it looks for the manual user’s winning positions. If its able to find them, it blocks it. If not the next available position is filled. The game can be played by clicking any of the squares below.

Here is the code for the game as a silverlight application. The complete project can be downloaded here.

The XAML is quite simple. Just a grid with three rows and three columns

    <grid x:Name="gridGame" Background="White" Width="300" Height="300" HorizontalAlignment="Center" VerticalAlignment="Center">
        </grid><grid .RowDefinitions>
            <rowdefinition Height="100" />
            <rowdefinition Height="100" />
            <rowdefinition Height="100" />
        </grid>
        <grid .ColumnDefinitions>
            <columndefinition Width="100" />
            <columndefinition Width="100" />
            <columndefinition Width="100" />
        </grid>

It is then filled with the buttons in the Code Behind. I have hardcoded the grid size of three but this will work with any size.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 public MainPage()
        {
            InitializeComponent();
            InitializeGameLogic(true);
        }
 
        private void InitializeGameLogic(bool _fromConstructor)
        {
            if (!_fromConstructor)
            {
                gridGame.Children.Clear();
            }
            _logic = new TicTacLogic();
            for (int i = 0; i < 3; i++)
                for (int j = 0; j < 3; j++)
                {
                    Button _btnGrid = new Button();
                    _btnGrid.Name = "btn" + i.ToString() + j.ToString();
                    gridGame.Children.Add(_btnGrid);
                    Grid.SetRow(_btnGrid, j);
                    Grid.SetColumn(_btnGrid, i);
                    _btnGrid.Height = 80;
                    _btnGrid.Width = 80;
                    _btnGrid.Click += new RoutedEventHandler(_btnGrid_Click);
                }
            _logic.StartGame();
        }

All the dynamically generated buttons have a single event handler. The idea is to identify the button which sent the event from the name. Once we have the position of the button, the content has to be changed with an X. After the user marks, the computer does its stuff and makes its move. After every marking, a check is done if someone has won or the board is full.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
void _btnGrid_Click(object sender, RoutedEventArgs e)
        {
            Button _userClicked = sender as Button;
            int _xPos = Convert.ToInt32(_userClicked.Name.Substring(3,1));
            int _yPos = Convert.ToInt32(_userClicked.Name.Substring(4,1));
            _userClicked.Content = GetMarking("X");
            _logic.ClickUser(_xPos, _yPos);
            if (!(_logic.CheckIfSomeoneWon() || _logic.CheckIfBoardFull()))
            {
                int _xCom = 0;
                int _yCom = 0;
                _logic.MoveComputer(ref _xCom, ref _yCom);
                foreach (UIElement _tempElem in gridGame.Children)
                {
                    Button _comBtn = _tempElem as Button;
                    if (_comBtn != null && _comBtn.Name == "btn" + _xCom + _yCom)
                    {
                        _comBtn.Content = GetMarking("O");
                        break;
                    }
                }
                if (_logic.CheckIfSomeoneWon() || _logic.CheckIfBoardFull())
                    InitializeGameLogic(false);
            }
            else
                InitializeGameLogic(false);
 
        }
 
        private TextBlock GetMarking(string _mark)
        {
            TextBlock _t = new TextBlock();
            _t.Text = _mark;
            _t.FontSize = 25;
            _t.FontWeight = FontWeights.Bold;
            return _t;
        }

The Board class maintains two important things. The position of all the squares and which player has it marked. The Board doesnt depend on the Player objects. It has an object of the WinningPositions object which calculates the winning positions which can be compared with later. This object makes it possible to play with larger grids.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
public class Board
{
    readonly int MAXSIZE;
    List<positionmarking> _boardState = new List</positionmarking><positionmarking>();
    List<position []> _allWinningPositions;
 
    public List<positionmarking> BoardState { get { return _boardState; } }
    public List<position []> AllWinningPositions { get { return _allWinningPositions; } }
    public int MaxSize { get { return MAXSIZE; } }
 
    public Board()
    {
        this.MAXSIZE = 3;
        Initialize();
    }
 
    public Board(int _maxSize)
    {
        MAXSIZE = _maxSize;
        Initialize();
    }
 
    private void Initialize()
    {
        _allWinningPositions = (new WinningPositions(MAXSIZE)).AllWinningPositions;
        for(int _xPos=0;_xPos<maxsize ;_xPos++)
            for (int _yPos = 0; _yPos < MAXSIZE; _yPos++)
            {
                _boardState.Add(new PositionMarking(_xPos,_yPos));
            }
    }
 
    internal void MarkPosition(int _xUser, int _yUser, bool _userMarked)
    {
        foreach (PositionMarking _tempPos in _boardState)
        {
            if (_tempPos.BoardPosition.X == _xUser && _tempPos.BoardPosition.Y == _yUser)
            {
                _tempPos.MarkPosition(_userMarked);
                break;
            }
        }
#if DEBUG
        PrintBoardState();
#endif
    }
 
    internal bool? MarkedByUser(Position _tempPos)
    {
        foreach (PositionMarking _tempMark in _boardState)
        {
            if (_tempPos.X == _tempMark.BoardPosition.X && _tempPos.Y == _tempMark.BoardPosition.Y)
                return _tempMark.IsUserMarked;
 
        }
        throw new Exception("Position Not found on Board");
    }
 
    #if DEBUG
    internal void PrintBoardState()
    {
        string _userMarked = "";
        string _compMarked = "";
        foreach (PositionMarking _tempMark in _boardState)
        {
 
            if (_tempMark.IsUserMarked == true)
                _userMarked += "("+ _tempMark.BoardPosition.X + "," + _tempMark.BoardPosition.Y + ") ";
            else if (_tempMark.IsUserMarked == false)
                _compMarked += "(" + _tempMark.BoardPosition.X + "," + _tempMark.BoardPosition.Y + ") ";
        }
        Debug.WriteLine("USER: " + _userMarked);
        Debug.WriteLine("COMP: " + _compMarked);
        Debug.WriteLine("________________________________________");
    }
#endif
    internal bool IsBoardFull()
    {
        foreach (PositionMarking _tempMark in _boardState)
        {
            if (_tempMark.IsUserMarked == null)
                return false;
 
        }
        MessageBox.Show("Board Full");
        return true;
    }
}

The Winning Position class is given below and all positions are calculated at initialization. First the horizontal ones are considered and then the vertical ones. The remaining diagonal positons are taken care later. Each winning position is stored in an array of the position object which just holds the value of the Squares. These arrays are stored in a generic List.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public class WinningPositions
{
    List<position []> _allWinningPositions = new List</position><position []>();
    Position[] _winPos1;
    Position[] _winPos2;
 
    public List</position><position []> AllWinningPositions
    {
        get { return _allWinningPositions; }
    }
 
    public WinningPositions(int _maxSize)
    {
        _winPos1 = new Position[_maxSize];
        _winPos2 = new Position[_maxSize];
        PopulateWinningPositions();
    }
 
    private void PopulateWinningPositions()
    {
        int _iCounter=0;
        int _xPos = 0;
        int _yPos = 0;
        for (_xPos = 0; _xPos < _winPos2.Length; _xPos++)
        {
            for (_yPos = 0; _yPos < _winPos2.Length; _yPos++)
            {
                _winPos1[_iCounter] = new Position(_xPos, _yPos);
                _winPos2[_iCounter] = new Position(_yPos, _xPos);
                _iCounter++;
            }
            _allWinningPositions.Add(_winPos1);
            _allWinningPositions.Add(_winPos2);
            _winPos1 = new Position[_winPos1.Length];
            _winPos2 = new Position[_winPos2.Length];
            _iCounter = 0;
        }
        _iCounter = 0;
        for (_xPos = 0, _yPos = 0;_xPos < _winPos1.Length; _xPos++, _yPos++)
        {
            _winPos1[_iCounter] = new Position(_xPos, _yPos);
 
            _iCounter++;
        }
        _allWinningPositions.Add(_winPos1);
        _iCounter = 0;
        for (_xPos = 0, _yPos = _winPos1.Length - 1; _xPos < _winPos1.Length; _xPos++, _yPos--)
        {
            _winPos2[_iCounter] = new Position(_xPos, _yPos);
            _iCounter++;
        }
        _allWinningPositions.Add(_winPos2);
    }
}

Then there is the Player class of which we create two objects. The user takes care of his own moving logic, all we need to do is to change the state of the square for him. But the computer has its method called the SmartMove. Here we first move through the winning positions to identify any open squares that can be marked. If there are no squares, then we look to block the opponent’s winning. If even this opportunity is not found, we mark an available open square.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
public class Player
{
    Board _currentBoardPosition;
    bool _isComputer;
    List<position> _allMarkedPositions;
 
    public Player(bool _isComputer,Board _currentBoardPos)
    {
        this._isComputer = _isComputer;
        _allMarkedPositions = new List</position><position>();
        _currentBoardPosition = _currentBoardPos;
    }
 
    internal void SmartMove(ref int _xCom, ref int _yCom)
    {
        bool _markingDone = false;
        bool _blockUser = false;
        Position _userBlock = new Position();
        foreach (Position[] _winPos in _currentBoardPosition.AllWinningPositions)
        {
            int _userMarked = 0;
            int _computerMarked = 0;
            int _nullMarked=0;
 
            Position _openPos= new Position();
            foreach (Position _tempPos in _winPos)
            {
                bool? isUserMarked = _currentBoardPosition.MarkedByUser(_tempPos);
                if (isUserMarked==true)
                    _userMarked++;
                else if (isUserMarked == false)
                    _computerMarked++;
                else
                {
                    _openPos = _tempPos;
                    _nullMarked++;
                }
 
            }
            if (_computerMarked == 2 && _nullMarked == 1)
            {
                Debug.WriteLine("Wining block: " + _openPos.X + "," + _openPos.Y);
                _currentBoardPosition.MarkPosition(_openPos.X, _openPos.Y, false);
                _xCom = _openPos.X;
                _yCom = _openPos.Y;
                _markingDone = true;
                break;
            }
            else if (_userMarked == 2 && _nullMarked == 1)
            {
                _userBlock = _openPos;
                _blockUser = true;
            }
 
        }
        if (_blockUser && !_markingDone)
        {
            _currentBoardPosition.MarkPosition(_userBlock.X, _userBlock.Y, false);
            _xCom = _userBlock.X;
            _yCom = _userBlock.Y;
            _markingDone = true;
        }
 
        if (!_markingDone)
        {
 
            //No Winning Position Found or not able to block;
            foreach (PositionMarking _posMark in _currentBoardPosition.BoardState)
            {
                if (_posMark.IsUserMarked == null)
                {
                    _markingDone = true;
                    _currentBoardPosition.MarkPosition(_posMark.BoardPosition.X, _posMark.BoardPosition.Y,false);
                    _xCom = _posMark.BoardPosition.X;
                    _yCom = _posMark.BoardPosition.Y;
                    break;
                }
            }
 
        }
    }
}
</position>

Since the Board needs to maintain the state of each and every position on itself, we have another object for it, which maintains a position object and a nullable boolean. If the boolean is true, then the square is marked by the user, if false – then by the computer. If its still null – its open and can be marked. The marking is done by the object’s method which makes a check to make sure no players marking is overwritten by another.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class PositionMarking
{
    Position _boardPos;
    bool? _isUserMarked;
 
    public Position BoardPosition { get { return _boardPos; } }
    public bool? IsUserMarked { get { return _isUserMarked; } }
 
    public PositionMarking(int _xPos,int _yPos)
    {
        _isUserMarked = null;
        _boardPos = new Position(_xPos, _yPos);
    }
 
    public void MarkPosition(bool _markedByUser)
    {
        if(_isUserMarked == null)
        _isUserMarked = _markedByUser;
        else
        throw new Exception("Position already taken");
    }
}

Then there is the rest of the code including our business logic layer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
public class TicTacLogic
{
    bool _userToMove;
    bool _resultHasCome;
    Player _user;
    Player _computer;
    Board _gameBoard;
 
    public TicTacLogic()
    {
        _userToMove = true;
        _resultHasCome = false;
    }
 
    internal void StartGame()
    {
        Initialize();
    }
 
    internal bool ClickUser(int _xUser, int _yUser)
    {
        return _gameBoard.MarkPosition(_xUser, _yUser, true);
    }
 
    internal void MoveComputer(ref int _xCom, ref int _yCom)
    {
        _computer.SmartMove(ref _xCom, ref _yCom);
    }
 
    internal void Initialize()
    {
        _gameBoard = new Board(3);
        _user = new Player(false,_gameBoard);
        _computer = new Player(true,_gameBoard);
 
    }
 
    public bool CheckIfSomeoneWon()
    {
        foreach (Position[] _tempWin in _gameBoard.AllWinningPositions)
        {
            int _userWon=0;
            int _compWon=0;
            foreach (Position _p in _tempWin)
            {
                bool? isUserMarked = _gameBoard.MarkedByUser(_p);
                if (isUserMarked == null)
                    break;
                else if (isUserMarked == true)
                    _userWon++;
                else
                    _compWon++;
 
            }
            if (_userWon == _gameBoard.MaxSize)
            {
                MessageBox.Show("User Won");
                return true;
            }
            else if (_compWon == _gameBoard.MaxSize)
            {
                MessageBox.Show("Computer Won");
                return true;
            }
 
        }
        return false;
    }
 
    internal bool CheckIfBoardFull()
    {
        return _gameBoard.IsBoardFull();
    }
}
 
public class Position
{
    int _xPos;
    int _yPos;
 
    public Position()
    {
    }
 
    public int X { get { return _xPos; } }
    public int Y { get { return _yPos; } }
 
    public Position(int xPos, int yPos)
    {
        this._xPos = xPos;
        this._yPos = yPos;
    }
}

Nov 252009
 

In my previous blog, I wrote about the simplest form of animation in Silverlight – the FromTo animation, which allows you to modify the value of Control properties thus giving animation effects like Fading in-out, movement and many more. KeyFrame animation is different as in it gives you more control in defining both the duration and the value of the property in each animation.

Like in the FromTo animation, you can set the Target, AutoReverse, BeginTime and RepeatBehavior for KeyFrame as well. Lets look at a simpleKeyFrame animation. In this we manipulate both the Color and the FontSize property. The SplineDoubleKeyFrame property has a key and value pair which allows us to specify the value at that exact point of time.

Here is the markup.

<Grid x:Name="LayoutRoot" Height="Auto" Width="300">
       <Grid.Triggers>
           <EventTrigger RoutedEvent="Grid.Loaded">
               <TriggerActionCollection>
                   <BeginStoryboard>
                       <Storyboard>
                           <DoubleAnimationUsingKeyFrames
               Storyboard.TargetName="AnimateText"
               Storyboard.TargetProperty="FontSize"
               BeginTime="00:00:00"
               RepeatBehavior="Forever"
                               AutoReverse="True">
                               <SplineDoubleKeyFrame KeyTime="00:00:02" Value="50" />
                               <SplineDoubleKeyFrame KeyTime="00:00:06" Value="75" />
                               <SplineDoubleKeyFrame KeyTime="00:00:08" Value="90" />
                               <SplineDoubleKeyFrame KeyTime="00:00:10" Value="80" />
                               <SplineDoubleKeyFrame KeyTime="00:00:14" Value="35" />
                           </DoubleAnimationUsingKeyFrames>
                           <ColorAnimationUsingKeyFrames
                               Storyboard.TargetName="solidBrush"
                               Storyboard.TargetProperty="Color"
                               BeginTime="00:00:00"
                               RepeatBehavior="Forever"
                               AutoReverse="True">
                               <SplineColorKeyFrame KeyTime="00:00:02" Value="Red" />
                               <SplineColorKeyFrame KeyTime="00:00:04" Value="Blue" />
                               <SplineColorKeyFrame KeyTime="00:00:06" Value="Black" />
                               <SplineColorKeyFrame KeyTime="00:00:08" Value="Beige" />
                               <SplineColorKeyFrame KeyTime="00:00:10" Value= "DarkGreen" />
                           </ColorAnimationUsingKeyFrames>
                       </Storyboard>
                   </BeginStoryboard>
               </TriggerActionCollection>
           </EventTrigger> 
       </Grid.Triggers>
       <TextBlock x:Name="AnimateText" 
                  FontSize="35" 
                  Text="Hello World"
                  TextWrapping="Wrap"
                  >
           <TextBlock.Foreground>
               <SolidColorBrush x:Name="solidBrush"
                                Color="Black" />
           </TextBlock.Foreground>
       </TextBlock>
      
   </Grid>

Here is the sample:-


Get Microsoft Silverlight

Nov 212009
 

Displaying a slideshow of various images is a very common requirement these days. It can be done very easily using the Transtion Control in Silverlight Control Toolkit. Lets see how.

First create a Silverlight Application using Visual Web Developer.
newProject

The Transition Control is a part of the Toolkit, which we need to add a reference to. Right click References, Click Add Reference and choose  System.Windows.Controls.Layout.Toolkit.

addRef

Now that we added the reference, we also need to add the namespace in the XAML page.

xmlns:transition="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Layout.Toolkit"

Now comes the page markup, This page contains a grid separated into two columns. One with the Transition Control and one with the Button to make the switch.

<UserControl x:Class="SLTransition.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:transition="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Layout.Toolkit"
   Height="360"  Width="460" >
  <Grid x:Name="LayoutRoot" Height="300" Width="400" Margin="30">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="325" />
            <ColumnDefinition Width="75" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
        </Grid.RowDefinitions>
        <transition:TransitioningContentControl
            Name="imageTransition"
            Grid.Column="0"
            Grid.Row="1"
            HorizontalAlignment="Stretch"
            VerticalAlignment="Stretch"
            Transition="DownTransition" />
        <Button x:Name="Next"
              Width="50"
              Height="30"
              HorizontalAlignment="Center"
              VerticalAlignment="Center"
              Grid.Row="0"
              Grid.Column="1"
              Content="Next"/>
    </Grid>
</UserControl>

Now the code to make the transition work. There are two class level variables in the MainPage.xaml.cs page. One is the counter to iterate through the pictures and another a string array containing the names of the image files. I didn’t give the extension here and gave it later, but you can do it in the array as well, which would be needed if you are going to use images of different formats.

int _counter = 0;
string[] _picNames = { "A", "B","C","D","E","F","G" };

Now the constructor and the Next Button Click event handler. In the constructor the click event handler is added for the next button and then the Silverlight transition control is populated with the first image in the string array. The counter is then incremented. In the next button click handler, we populate the Silverlight transition control with the image of the current counter value and increment the counter value again.

public MainPage()
{
    InitializeComponent();
    Next.Click += new RoutedEventHandler(Next_Click);
    imageTransition.Content = GetImage(0);
    _counter++;
}

void Next_Click(object sender, RoutedEventArgs e)
{
    imageTransition.Content = GetImage(_counter);
    _counter++;
}

Now the code to retrieve the image from the string array. First if the counter has reached the limit of the string array, then we reset it to 0. Then the path is constructed from the string array and set as an Image and returned to the calling function which sets the Silverlight Transition Control’s Content Property. Since the image class inherits from FrameworkElement, it can be set as the Content.

Image GetImage(int _counter)
{
    if (_counter >= _picNames.Length)
        this._counter = 0;
    Image _image = new Image();
    Uri _uri = new Uri(_picNames[this._counter] + ".jpg", UriKind.Relative);
    ImageSource _imgSource = new BitmapImage(_uri);
    _image.SetValue(Image.SourceProperty, _imgSource);
    return _image;
}

Also the images must be copied to the Silverlight project for it to find. Thats it, the image transition control will work perfectly. See it in action below. I used some pics of the Wonders of the World. Click the next button to view the transition. This is the DownTransition, the other values for this control are UpTransition, DefaultTransition and Normal.


Get Microsoft Silverlight

Nov 122009
 

The audience which the web was catering to, has drastically changed in the last 10 years. From primary being a one way of source of information for its users, the web has evolved into a massive aggregator with which users can both create and consume information. This meant a sea change for web developers and application designers where they had to make their User interface much more interactive and closer to windows applications.

Adobe Flash and Microsoft Silverlight are a step in that direction. Groundbreaking animation is possible with these technologies. We will take a look at some simple animation in Silverlight today. First the simplest animation possible. The Double animation works by moifying a double property of the application in a time bound way. Suppose we want to create a rectangle that disappears and reappears every second. Lets take a look at the XAML.

<UserControl x:Class="SLAnimation.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"
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
  <Grid x:Name="LayoutRoot">
        <StackPanel >
            <StackPanel.Resources>
                <Storyboard x:Name="AppStoryBoard">
                    <DoubleAnimation x:Name="clickAnim"
                                     Storyboard.TargetName="animRectangle"
                                     Storyboard.TargetProperty="Opacity"
                                     From="1.0" To="0.0" Duration="0:0:1"
                                     AutoReverse="True"
                                     RepeatBehavior="Forever" />
                </Storyboard>
            </StackPanel.Resources>
            <TextBlock TextAlignment="Center" FontSize="30" FontFamily="Verdana">Double Animation in Silverlight</TextBlock>
            <Rectangle x:Name="animRectangle" MouseLeftButtonDown="animRectangle_MouseLeftButtonDown"
                       Width="200" Height="100" Fill="Red" ></Rectangle>
        </StackPanel>
    </Grid>
</UserControl>

If you see this code, the animation is defined in the Storyboard tag which contains the code of how exactly the animation will behave. It specifies the target control and also the property which has to be altered. Then we give the for loop for changing the transparency along with the step property. Once the story board is done, you need to write the control which is the target of the StoryBoard, a simple rectangle. However, a presence of a storyboard is not enough to start the animation. This is done in the code behind.

        public MainPage()
        {
            InitializeComponent();
        }
 
        private void animRectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            AppStoryBoard.Begin();
        }

Even this can be achieved through XAML alone as we will see in the next example. In this looping animation two rectangles will move to the opposite ends of the canvas before returning. The best part is there is no code behind involved. The Storyboard is triggered by the EventTriggers tag in Silverlight. This time the property that is modified is the Canvas.Left. One rectangle already has this property set to 0 and one has it to 280. And in the storyboard, there are respective DoubleAnimation tags added. One of them increases the first rectangle’s Canvas.Left property from 0 to 280 and the other vice versa. Since the RepeatBehavior is set to Forever, it seems like an endless loop.

<Canvas>
<Canvas.Triggers>
<EventTrigger RoutedEvent="Canvas.Loaded" >
<EventTrigger.Actions>
    <BeginStoryboard>
        <Storyboard x:Name="animRectangle1"
                    Storyboard.TargetName="Rectangle1"
                    Storyboard.TargetProperty="(Canvas.Left)" RepeatBehavior="Forever">
            <DoubleAnimation To="280" Duration="0:0:15"></DoubleAnimation>
            <DoubleAnimation To="0" Storyboard.TargetName="Rectangle2" Duration="0:0:15"></DoubleAnimation>
        </Storyboard>
    </BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Canvas.Triggers>
<TextBlock TextAlignment="Center" FontSize="30" FontFamily="Verdana">Moving Animation in Silverlight</TextBlock>

<Rectangle x:Name="Rectangle1" Canvas.Left="0" Canvas.Top="40" Width="20" Height="20" Fill="red"></Rectangle>
<Rectangle x:Name="Rectangle2" Canvas.Left="280" Width="20" Canvas.Top="40" Height="20" Fill="Blue"></Rectangle>
</Canvas>

So we saw how easy it is to create simple animation with Silverlight. Below is a simple preview of the application. And as one more demonstration of the platform independent nature of Silverlight, I just wrote the object tag for the Silverlight .xap file and thats it, it works in WordPress’s PHP without any hiccups.

Get Microsoft Silverlight

Nov 082009
 

Microsoft Silverlight 3 includes support for creating Rich Internet Applications with virtually no code at all. In this article, I will create a simple RIA application which displays data from the SQL Server 2005 AdventureWorks database. For those who are wondering what RIA services are? Its a pattern which integrates ASP.NET with Silverlight and provides a simple way to write n-tier applications. What I admired about RIA services applications are it brings your database logic to your business layer. What that means is that your database and Data access layer virtually contains no application specific code at all. In future, upgrading, migrating to any other database is amazingly simple. There is the element of a performance implication while using Linq though, which needs to be taken into consideration. Thanks to Sachin Rathi from Microsoft for his session in TechDays where he taught about this new topic.

So lets jump into it. First the tools, which can be downloaded from here. The fifth point in the list is the RIA kit. Once thats done, you would have a new template – Silverlight Business Application.

newProject

So like we saw in the previous blog, there are two applications created – one for our Silverlight application and one for the ASP.NET application. The basic application is already created with a decent theme.

businessApp

Lets create a new xaml page for displaying our data created by the RIA applications. Right click on the Views folder and add a new Silverlight page.

addnewPage

addnewItem

Now that the new Silverlight page is created, lets add a link to it from the main page. Add this markup after the link to the about page.

<Rectangle x:Name=”Divider2″ Style=”{StaticResource DividerStyle}”/>
<HyperlinkButton x:Name=”Link3″ Style=”{StaticResource LinkStyle}”
NavigateUri=”/EmployeesPage” TargetName=”ContentFrame” Content=”Employees”/>
Once thats done, we need to add any database from which to retrieve data from. I will use the sample AdventureWorks database. Copy the database file to the App_Data folder. Now what is needed is a Entity Data model. The Entity data model generates a ER data model by analyzing the database. Right click on the web project and add a new item – AdventureWorks.edmx. In the next screen click on Generate from database. The ED model automatically detects the database files and generates the connection string. Click next and select the employee table alone in the next screen.
edmxModel
edmodel
This step generates the entity relationship model for the database, and make the code “aware” of the underlying database. In later steps we could write Linq queries against the database. The next step would be to add a new domain service class, the item template for which has been installed already.
domainService
domainServiceOpts
To the domain service class that was automatically generated, add a new method GetSalariedEmployees.
public IQueryable<Employee> GetEmployees()
{
return this.Context.Employee;
}
public IQueryable<Employee> GetSalariedEmployees()
{
return this.Context.Employee
.Where(emp => emp.SalariedFlag == true);
}
Then add a new datagrid to the EmployeesPage.xaml. A reference needs to be added to the Windows.Controls.Data assembly. Also a namespace is added to the datagrid. The markup is as below.
employeeMarkup
Now that the datagrid is loaded, lets add the namespace for the Application in the xaml page. Here is the finished xaml file.
finishedXaml
It can also be done through code like this.
employees _eObj = new employees();
public EmployeesPage()
{
InitializeComponent();
this.dataGrid.ItemsSource = _eObj.Employees;
_eObj.Load(_eObj.GetEmployeeQuery());
}

This application is by no means over, we can add sorting, filtering, updating rows to this with as little code as possible. More about it in future posts.

Nov 072009
 

Silverlight is Microsoft’s answer to Adobe Flash, used to display multimedia, animation and graphics in Internet applications. Its a subset of Windows Presentation Foundation and uses a vector graphics rendering engine to deliver much better graphics than conventional web images.

With each release Microsoft is working on bringing Silverlight and WPF closer to each other. Prism is one such implementation which allows applications to be written without knowing the end platform in mind. In this blog I will explain how to write a simple application and XCOPY deploy it to a shared web hosting provider, in my case godaddy.

First open up Visual Studio. For this walkthrough I have used Visual Web Developer 2008 which is a free software and can be downloaded here. You would also need the Silverlight SDK consisting of the runtime environment and the toolkit, all of which can be downloaded at the Silverlight page.

First open up Visual Web Developer. Click on File -> New Project. If the tools were installed correctly, you should see a new Project type Silverlight Application in the list.

newProject

The next screen asks if you want to host your silverlight application in an ASP.NET website. This is really optional since Silverlight is independant from ASP.NET. It can be hosted on your HTML, PHP, JSP application with equal ease. The only thing needed is the .XAP file.

newApp

The solution is created and if you look at it there, are two projects. One is the Silverlight project with App.xaml and MainPage.xaml. Another project is the ASP.NET website which is the host for the Silverlight application. The xap file is contained in the ClientBin folder.

Solution_Exporer

In the godaddy Hosting manager, click on IIS management and create a virual directory which is setup as an application.

IISSettings

Now lets see the project. Click on MainPage.xaml to see the markup for the MainPage. Copy this markup between the grid element. Unfortunately the HTML tags aren’t working properly when I copy paste them to the blog. Hence posting the screenshot.

postMarkup

Then you need to modify the web.config and set the custom errors mode = off. Then using a FTP client copy all the host website files into the virtual directory that you created. And thats it. Your first sample silverlight website.