![]() |
Platforms, Frameworks & Libraries »
Windows Presentation Foundation »
General
Intermediate
License: The Code Project Open License (CPOL)
Comparing Flash and WPFBy Sacha BarberComparing Flash and WPF |
C# 3.0, .NET, Vista, WPF, VS2005, Dev
|
||||||||||||
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
There has been a lot of talk lately about WPF/Silverlight. I have also been learning and writing WPF articles, but what I thought might make an interesting article would be to compare and contrast WPF/Flash.
I feel I have the right to do this, as I have worked with both technologies, and although I am not selling myself as an expert in either, I feel confident enough to write this article, I thought it would just make some interesting reading for others that just dont know how WPF or Flash work. For example if you're a Flash developer and dont know what WPF is, I am hoping this article will help you, and vise versa.
I should firstly mention that I only have Flash MX 2004, which I believe is Flash 7.0, which used the 2nd generation of Flash scripting language (action script 2, here after known as AS2). Since then Macromedia have obvioulsy been bought by Adobe, who have created Creative Studio 3 (CS3) which includes Flash under this general umbrella. Not only that, but they have totally re-written the scripting side of things in Flash, and it is now action script 3 (here after known as AS3). I know nothing about AS3 except that it will be Java like, and will allow OO type stuff like inheritence etc etc, but I do have a excellent Flash developer friend, that assures me that writing about AS2 will not be a waste of time, as although its different, the areas i'm going to cover in this article are still the same. So ill stick to writing about AS2 if its ok with your lot. After all people are still writing about .NET 2.0, jeez that soo old man .NET 3.0/3.5 are here, come on man get with the program. No only kidding what ever floats your boat is ok by me, I write about what I like. Period. If others like it great, if not thats also fine, ill still carry on writing about stuff I like.
I think the easiest way to start it to just go through features one at a time. I am specifically only picking on features that WPF introduced, otherwise this would be a very very long and tideous article. By this I mean I will not discuss threading, sockets, databases, remoting, xml handling specifically, though Flash is more than capable of all of these with the exception of threading.
Below is a list of things that I think Flash / WPF people would like to know about each others worlds
So shall we continue, what im going to do is under each of the heading below, have a Flash view point followed by a WPF viewpoint, that way people should be able to see what the various pros and cons are for themselves.
Flash
Before we get on to how to code in Flash its fairly important to understand how Flash works at a conceptual level. So lets start there shall we.
Flash is based on a library of reources which can be created on an initial stage (work area) and then grouped together to form either a Button/ Graphic or a MovieClip. When created these grouping of stage objects into one of the 3 objects just mentioned, can be added to the library (more on this later) as resources. Later on the library components can be brought to the stage either manually (dragged on to stage) or programatically (the right way IMHO).
The stage is basically constructed of layers down and time across. See the figure below, which shows 2 simple rectangles (no animation yet) on the stage on different layers
The stage allows user to create the following :
MovieClip object for example. For those of you that have never used Flash, it has its own language support, this is known as Action Script. The latest version of Flash (the one in Adobe CS3 product) uses Action Script 3 (AS3). I dont have access to that though, so ill be discussing things using Flash MX 2004 which uses AS2.
So what can we do with this Action Script stuff. Well as it turns out we can do quite a lot actually.
The way that Flah have developed Action Script is quite cool and what one would expect coming from an OO language. AS2 was not 100% OO but it was a damn fine start. There was and still is no threading support, but apart from that, I think its a nice set of classes and libraries/operators and keywords.
There are pre built classes for working with MovieClips, Sound, Video, Web Cams, Sockets, Event handling, and also the usual collections, if-then-else, loops, Maths classes. We can subclass existing controls, create new control and classes etc etc. Its quite mature actually, even better in the new AS3, which will be 100% OO.
So now that we know that we have these classes available what can we do with them, and how to I trigger a bit of Action Script to run in the 1st place.
Well thats actually very very easy, all we need to do is create an Action of a frame or an object. An example is shown below, where I am creating an action on Frame1 of the stage. When an action exists for a key frame a lilttle "a" will be shown for that frame on the stage.
It can be seen from this small screen shot that we can create functions, call methods on existing classes. And whats this 1st line doing
attachManager = new AttachManager();
That kind of looks like its creating an object doesnt it. Well yes that exactly what its doing, we can creat objects in Flash action script, that will bring to life external Action Script Files and create objects from them. Shall we take a sneaky peak at what this external action script file looks like
// \\\\\\\\\\\\\\ // // AttachManager class : Allows movie to be added to the timeline using // scripting. The movies will be added using the linkage name within the // library. The attach method also returns the attached MovieClip to the // timeline. This class is instatiated from the _level0 timeline using action // script like // // attachManager = new AttachManager() // // var movie1 = attachManager.attach('movie1', 0, 0) // // \\\\\\\\\\\\\\\ class AttachManager{ //instance fields private var attachArr:Array; private var i:Number; //constructor function AttachManager(){ //holding array for all objects the manager holds attachArr = new Array(); } //attach : Attaches the object to the timeline using the parameters // provided // //PARAMETERS : //linkage:String : A string representing the linkage name for the object // to attach //xpos:Number : The X-Pos to use for the object to attach //ypos:Number : The Y-Pos to use for the object to attach //depth : The depth to use, where the object will be attached. In action //script depth goes from 0 downwards where as in flash depth goes from 0 // upwards // //RETURNS : //MovieClip : that may be used by the flash timeline via action script public function attach(linkage:String, xpos:Number, ypos:Number,depth):MovieClip { //get the depth if no depth exists yet if(depth==undefined){ depth = getCurDepth(); } //now do the attaching to _level0, using the paraaddEventListenermeters // porovided var tmpClip = _level0.attachMovie(linkage,linkage,depth,{_x:xpos,_y:ypos}) tmpClip._name=linkage; //store the object in the holding array attachArr.push(tmpClip) //return the newly attached MovieClip return tmpClip; } //getCurDepth : Get the HighestDepth for the timeline // //RETURNS : //Number : that represents the HighestDepth for the timeline public function getCurDepth():Number { //return the depth return _level0.getNextHighestDepth(); } //killClip : Removes an object from the AttachManager // //PARAMETERS : //clip : the object to remove from the internal holding array public function killClip(clip) { //remove the clip _level0.removeMovieClip(clip); } //removeAllClips : Removes all objects from the AttachManager public function removeAllClips() { //remove all clips in holding array for(i=0; i < attacharr.length;)
Its a class, just like one would create in any other OO type language. So by using a combination of components, library resources, stage action script, and external action script (.as files) we can make some pretty powerful Flash applications. Oh if you want to get into writing action script seriously, I would recommend that you download the Sepy action script editor which is available here
IMPORTANT NOTE : Although the stage is convenient, it can quickly becoming cluttered with layer/objects/animations if you only use the stage. A better way is to develop seperate parts of the UI which all do specific tasks and then create these tasks in small components (MovieClip objects are best) that are brought to the stage either manually or by action script (which is discussed in the resources section of this article), which keeps the stage nice and tidy. A really good flash developer will probably have a single layer within the stage that has one frame which has actions assocviated with it, which will load all the other UI parts to the stage programatically. Of course each component will also have its own stage, thats how Flash works. Each MovieClip has its own stage.
So I hope that gives a basic understanding of the very basic idea behind how to create Flash applications
WPF is a truly OO language that also borrows ideas from ASP .NET. For example there is a view and code behind. The view part would be constructed of code known as XAML (Extensible Markup Language) which a Microsoft proprietary language, and looks a little like XML. But its way more powerful than simple XML, it is possible to make an entire event/animated datadriven application purely in XAML without and code behind at all. In the case where a code behind file is used, the code behind file will be either C# (the correct choice) or VB .NET (no dont do it).
So how does this all work, 2 files?
Lets consider a little example, a simple window with a single button control on it. Thats it.
This would result in the following XAML
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="UntitledProject1.Window1" x:Name="Window" Title="Window1" Width="640" Height="480"> <Grid x:Name="LayoutRoot"> <Button HorizontalAlignment="Left" Margin="101,118,0,0" x:Name="btn1" VerticalAlignment="Top" Width="188" Height="67" Content="Button"/> </Grid> </Window>
And we can access the Button control (btn1) from a code behind file just fine, as shown below
But how can this be. Well what happens is that there is an extra code file generated behind the scenes which contains all the objects that are defined in the XAML file, which allows the code behind file to access the XAML defined controls. This miracle is down to partial class support.
Shall we have a look at the generated code file for this simple example, which is a filled called Window1.g.cs which will be placed in the \Obj folder as part of the compilation process.
#pragma checksum "..\..\Window1.xaml" \
"{406ea660-64cf-4c82-b6f0-42d48172a799}" "FADEDA8B7804EA63C81E418EDBA03A95"
//----------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.1378
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//----------------------------------------------------------------------------
using System;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
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.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Media.TextFormatting;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace UntitledProject1 {
/// <summary>
/// Window1
/// </summary>
public partial class Window1 : System.Windows.Window,
System.Windows.Markup.IComponentConnector {
internal UntitledProject1.Window1 Window;
internal System.Windows.Controls.Grid LayoutRoot;
internal System.Windows.Controls.Button btn1;
private bool _contentLoaded;
/// <summary>
/// InitializeComponent
/// </summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater
= new System.Uri("/UntitledProject1;component/window1.xaml",
System.UriKind.Relative);
#line 1 "..\..\Window1.xaml"
System.Windows.Application.LoadComponent(this, resourceLocater);
#line default
#line hidden
}
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.ComponentModel.EditorBrowsableAttribute(
System.ComponentModel.EditorBrowsableState.Never)]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute(
"Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
void System.Windows.Markup.IComponentConnector.Connect(
int connectionId, object target) {
switch (connectionId)
{
case 1:
this.Window = ((UntitledProject1.Window1)(target));
return;
case 2:
this.LayoutRoot = ((System.Windows.Controls.Grid)(target));
return;
case 3:
this.btn1 = ((System.Windows.Controls.Button)(target));
return;
}
this._contentLoaded = true;
}
}
}
And our code behind file (C#)
using System;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
namespace UntitledProject1
{
public partial class Window1
{
public Window1()
{
this.InitializeComponent();
// Insert code required on object creation below this point.
}
}
}
So from these 3 listings you should be able to see how controls are accessable via the XAML and the codebehind files. But how do we use these controls. Well they are just classes, so we can call their methods, set the properties and listen to their events. As .NET is 100% OO we can sub class these standard classes and override the relevant methods should we wish to. And of which would occur in a XAML file or a code behind file. That said control Events will normally be handled in code behind, where custom logic may be performed
Unlike Flash there is no stage, there is a timeline feature used for animations, but thats about it. I wont discuss that yet, as its covered later on. This section was just meant to give you an idea of how Flash and WPF went about doing their thing.
Flash doesnt come with many controls as standard, as can be seen from the screen shots shown below.
This doesnt seem like a very big control set when compared to the .NET 3.0 controls available (remember we can still use System.Windows.Forms.Dll for dialogs and can even host windows forms components in WPF application) but what you need to understand with Flash is that we can apply actions (action script) to anything not just controls. This is way different from the windows programming model, where a control events are what we use to cause something to happen. For example I could have a single frame within the main stage that has action script aplied to it, or I could have a movie which is loaded dynamically and that could have its own actions associated within it, and it could also contain any of the controls shown above all of which expose their own events. In fact any object in Flash can be converted to a Graphic/MovieClip or Button all of which will the support action script being attached. Also remember that any AS2 code can also create external action script objects.
So on the face of it Flashes lack of a rich control heirachy doesnt seem to be much of a problem.
But what about custom controls?
Another nice thing about Flash ( well at least AS2/ AS3 version of Flash) is that you can also sub class these standard controls, just as you would for a WPF/ Win forms control. So its also fairly extensable.
I have Flash MX 2004 installed and if I examine the folder C:\Program Files\Macromedia\Flash MX 2004\en\First Run\Classes\mx\controls which is where all the standard components source code is stored I can see a load of different classes
So what do these look like, shall we have a look at one of these, lets pick a nice simple control, say a button. Well the AS2 code for this is shown below
I know this is a lot of code, but I thought it might be of interest to see how a standard Flash control was created
//**************************************************************************** //Copyright (C) 2003 Macromedia, Inc. All Rights Reserved. //The following is Sample Code and is subject to all restrictions on //such code as contained in the End User License Agreement accompanying //this product. //**************************************************************************** import mx.controls.SimpleButton; import mx.core.UIObject; import mx.core.UIComponent; /** * @tiptext click event * @helpid 3168 */ [Event("click")] [TagName("Button")] [IconFile("Button.png")] /** * Button class * - extends SimpleButton * - adds label and text with layout * - adds ability to resize without distorting the skin * @tiptext Button provides core button functionality. Extends SimpleButton * @helpid 3043 */ class mx.controls.Button extends SimpleButton { /** * @private * SymbolName for object */ static var symbolName:String = "Button"; /** * @private * Class used in createClassObject */ static var symbolOwner = mx.controls.Button; var className:String = "Button"; function Button() { } #include "../core/ComponentVersion.as" /** * number used to offset the label and/or icon when button is pressed */ var btnOffset:Number = 0; /** *@private * Color used to set the theme color */ var _color = "buttonColor"; /** *@private * Text that appears in the label if no value is specified */ var __label:String = "default value"; /** *@private * default label placement */ var __labelPlacement:String = "right"; /** //*@private * store the linkage name of the icon at initalization */ var initIcon; /** * @private * button state skin variables */ var falseUpSkin:String = "ButtonSkin"; var falseDownSkin:String = "ButtonSkin"; var falseOverSkin:String = "ButtonSkin" var falseDisabledSkin:String = "ButtonSkin"; var trueUpSkin:String = "ButtonSkin"; var trueDownSkin:String = "ButtonSkin"; var trueOverSkin:String = "ButtonSkin"; var trueDisabledSkin:String = "ButtonSkin"; var falseUpIcon:String = ""; var falseDownIcon:String = ""; var falseOverIcon:String = ""; var falseDisabledIcon:String = ""; var trueUpIcon:String = ""; var trueDownIcon:String = ""; var trueOverIcon:String = ""; var trueDisabledIcon:String = ""; /** * @private * list of clip parameters to check at init */ var clipParameters:Object = { labelPlacement:1, icon:1, toggle:1, selected:1, label:1 }; static var mergedClipParameters:Boolean = UIObject.mergeClipParameters(mx.controls.Button.prototype.clipParameters, SimpleButton.prototype.clipParameters); var labelPath:Object; var hitArea_mc:MovieClip; var _iconLinkageName:String; var centerContent : Boolean = true; var borderW : Number = 1;// buffer value for border /** * @private * init variables. Components should implement this method and call super.init() to * ensure this method gets called. The width, height and clip parameters will not * be properly set until after this is called. */ function init(Void):Void { super.init(); } /** * @private * */ function draw() { super.draw(); if (initIcon != undefined) _setIcon(initIcon); delete initIcon; } /** * This method calls SimpleButton's onRelease() */ function onRelease(Void):Void { super.onRelease(); } /** * @private * create children objects. Components implement this method to create the * subobjects in the component. Recommended way is to make text objects * invisible and make them visible when the draw() method is called to * avoid flicker on the screen. */ function createChildren(Void):Void { super.createChildren(); } /** * @private * sets the skin state based on tag and linkage name */ function setSkin(tag:Number,linkageName:String, initobj:Object):MovieClip { return super.setSkin(tag, linkageName, initobj); } /** * @private * sets the old skin's visibility to false and sets the new skin's *visibility to true */ function viewSkin(varName:String):Void { var skinStyle = getState() ? "true" : "false"; skinStyle += enabled ? phase : "disabled"; super.viewSkin(varName,{styleName:this,borderStyle:skinStyle}); } /** * @private * Watch for a style change. */ function invalidateStyle(c:String):Void { labelPath.invalidateStyle(c); super.invalidateStyle(c); } /** * @private * sets the color to each one of the states */ function setColor(c:Number):Void { for (var i=0;i<8;i++) { this[idNames[i]].redraw(true); } } /** * @private * this is called whenever the enabled state changes. */ function setEnabled(enable:Boolean):Void { labelPath.enabled = enable; super.setEnabled(enable); } /** * @private * sets same size of each of the states */ function calcSize(tag:Number, ref:Object):Void { if ((__width == undefined) || (__height == undefined)) return; if(tag < 7 ) { ref.setSize(__width,__height,true); } } /** * @private * Each component should implement this method and lay out * its children based on the .width and .height properties */ function size(Void):Void { setState(getState()); setHitArea(__width,__height); for (var i = 0; i < 8; i++) { var ref = idNames[i]; if (typeof(this[ref]) == "MovieClip") { this[ref].setSize(__width, __height, true); } } super.size(); } /** * sets the label placement of left,right,top, or bottom * @tiptext Gets or sets the label placement relative to the icon * @helpid 3044 */ [Inspectable(enumeration="left,right,top,bottom"defaultValue="right")] function set labelPlacement (val:String) { __labelPlacement = val; invalidate(); } /** * returns the label placement of left,right,top, or bottom * @tiptext Gets or sets the label placement relative to the icon * @helpid 3045 */ function get labelPlacement():String { return __labelPlacement; } /** * @private * use to get the label placement of left,right,top, or bottom */ function getLabelPlacement(Void):String { return __labelPlacement; } /** * @private * use to set the label placement to left,right,top, or bottom */ function setLabelPlacement(val:String):Void { __labelPlacement = val; invalidate(); } /** * @private * use to get the btnOffset value */ function getBtnOffset(Void):Number { if(getState()) { var n = btnOffset; } else { if(phase == "down") { var n = btnOffset; } else { var n = 0; } } return n; } /** * @private * Controls the layout of the icon and the label within the button. * note that layout hinges on a variable, "centerContents", which is *set to true in Button. * but false in check and radio. */ function setView(offset:Number):Void { var n = offset ? btnOffset : 0; var val = getLabelPlacement(); var iconW : Number = 0; var iconH : Number = 0; var labelW : Number = 0; var labelH : Number = 0; var labelX : Number = 0; var labelY : Number = 0; var lp = labelPath; var ic = iconName; // measure text size var textW = lp.textWidth; var textH = lp.textHeight; var viewW = __width-borderW-borderW; var viewH = __height-borderW-borderW; lp._visible = true; if (ic!=undefined) { iconW = ic._width; iconH = ic._height; } if (val == "left" || val == "right") { if (lp!=undefined) { lp._width = labelW = Math.min(viewW-iconW, textW+5); lp._height = labelH = Math.min(viewH, textH+5); } if (val == "right") { labelX = iconW; if (centerContent) { labelX += (viewW - labelW - iconW)/2; } ic._x = labelX - iconW; } else { labelX = viewW - labelW - iconW; if (centerContent) { labelX = labelX / 2; } ic._x = labelX + labelW; } ic._y = labelY = 0; if (centerContent) { ic._y = (viewH - iconH )/2; labelY = (viewH - labelH )/2 } if (!centerContent) ic._y += Math.max(0, (labelH-iconH)/2); } else { if (lp!=undefined) { lp._width = labelW = Math.min(viewW, textW+5); lp._height = labelH = Math.min(viewH-iconH, textH+5); } labelX = (viewW - labelW )/2; ic._x = (viewW - iconW )/2; if (val == "top") { labelY = viewH - labelH - iconH; if (centerContent) { labelY = labelY / 2; } ic._y = labelY + labelH; } else { labelY = iconH; if (centerContent) { labelY += (viewH - labelH - iconH)/2; } ic._y = labelY - iconH; } } var buff = borderW + n; lp._x = labelX + buff; lp._y = labelY + buff; ic._x += buff; ic._y += buff; } /** * sets the associated label text * @tiptext Gets or sets the Button label * @helpid 3046 */ [Inspectable(defaultValue="Button")] function set label(lbl:String) { setLabel(lbl); } /** * @private * sets the associated label text */ function setLabel(label:String):Void { if (label=="") { labelPath.removeTextField(); refresh(); return; } if (labelPath == undefined) { var lp = createLabel("labelPath", 200, label); lp._width = lp.textWidth + 5; lp._height = lp.textHeight +5; lp.visible = false; } else { labelPath.text = label; refresh(); } } /** * @private * gets the associated label text */ function getLabel(Void):String { return labelPath.text; } /** * gets the associated label text * @tiptext Gets or sets the Button label * @helpid 3047 */ function get label():String { return labelPath.text; } function _getIcon(Void):String { return _iconLinkageName; } /** * sets the associated icon * use setIcon() to set the icon * @tiptext Gets or sets the linkage identifier of the Button's icon * @helpid 3404 */ function get icon():String { if (initializing) return initIcon; return _iconLinkageName; } /** *@private * sets the icon for the falseUp, falseDown and trueUp states * use setIcon() to set the icon */ function _setIcon(linkage):Void { if (initializing) { if (linkage == "" ) return; initIcon = linkage; } else { if ( linkage == ""){removeIcons();return;} super.changeIcon(0,linkage); super.changeIcon(1,linkage); super.changeIcon(4,linkage); super.changeIcon(5,linkage); _iconLinkageName = linkage; refresh(); } } /** * @sets the icon for all states of the button * @tiptext Gets or sets the linkage identifier of the Button's icon * @helpid 3048 */ [Inspectable(defaultValue="")] function set icon(linkage) { _setIcon(linkage); } /** * @private * @method to set the hit area dimensions */ function setHitArea(w:Number,h:Number) { if (hitArea_mc == undefined) createEmptyObject("hitArea_mc",100); //reserved depth for hit area var ha = hitArea_mc; ha.clear(); ha.beginFill(0xff0000); ha.drawRect(0,0,w,h); ha.endFill(); ha.setVisible(false); }[ChangeEvent("click")] var _inherited_selected : Boolean; }
This looks pretty high level, doesnt it? Looks quite java/C# like I would say. Curly braces/attributes, mmm.
In later version of Flash it is also now possible to import a control from a 3rd party that has developed a new control using action script movie clips etc etc.
If we consider the standard controls that WPF provides (screen shot of Expression Blend) shown below
We can see straight away that there are a lot more controls. These controls can also be subclassed, which makes WPF very powerful. However we can still really only carry out operations based on user interaction with pre-existing control events or generated events within non UI classes. Remember in flash any frame or any object could potentially be made to run action script. So although there are more controls within WPF, there could potentially be many crazy controls within Flash, if we consider a MovieClip with actions on it to be a usercontrol. Which I think I would, wouldnt you.
Resources are very very important within Flash, resources are placed in a Library. The Libray can hold all sorts of things, such as sounds, Graphics, MovieClips, Tweens etc etc. Once an object is stored in the Library and has been given a name (which it will have to be allowed to be stored in the library in the 1st place) it can be dragged to the stage and used on any of the stage layers. But thats not all the library allows us to do. There is also another very important role the library plays, and that is the role of linkage.
Linkage is a key topic so listen up. What linkage does is allow a object in the library to manipulated programatically by action script. This will include bringing the object onto the stage / removing the object from the stage, calling the objects methods, subscribing to the object events. It basically exposes all the library objects functions to action script.
In fact this is how any good Flash developer should be doing things, its all about the linkage. By creating small components (MovieClips really) and only bringing them into life (the stage) when needed Flash is able to leverage some sort of JIT (Just In Time) model. I would think this would be the equivalent of declaring a new object in C# like SomeObject so = new SomeObject();. Shall we see an example of this
The following diagram illustrates this. It shows the library with a MovieClip object which has a linkage name of "moviePhoneOFF", which allows the MovieClip to be created and manipulated via Action Script as I am doing in this example
Resources are also a important part of WPF but they are fairly different from the way Flash talks about resources. We have 2 things to consider when discussing resources in WPF, firstly at file level and then at application level. Lets talks about file level first.
For this next section to make any sense youll probably need to be using Visual Studio 2005/2008
You can use file properties to indicate what actions the project system should perform on the files.
The BuildAction property indicates what Visual Studio does with a file when a build is executed. BuildAction can have one of several values:
None - The file is not included in the project output group and is not compiled in the build process. An example is a text file that contains documentation, such as a Readme file.
Compile - The file is compiled into the build output. This setting is used for code files.
Content - The file is not compiled, but is included in the Content output group. For example, this setting is the default value for an .htm or other kind of Web file.
Embedded Resource - This file is embedded in the main project build output as a DLL or executable. It is typically used for resource files. Specifying "Embedded Resource" puts the resource in the .mresource section of the assembly.
Page - Build action "Page" generates a performant BAML file.
Resource - Build action "Resource" generates an embedded XAML file.
The default value for BuildAction depends on the extension of the file you add to the solution. For example, if you add a Visual Basic project to Solution Explorer, the default value for BuildAction is Compile, because the extension .vb indicates a code file that can be compiled. File names and extensions appear in Solution Explorer.
An example of this is shown below for a resource file Dictionary1.xaml within a Visual Studio WPF project
So thats how to specify a build action, but thats only 1/2 the story. We still need to create the resource files in the first place. We are able to use resource files which will allow us to add string, images and icons. This is the same as .NET 2.0. But what about XAML resource files that are loaded dynamically. Well those are also called resources, but a special type of resource called a ResourceDictionary, which can contain markup that when imported can be used within the consumer of the ResourceDictionary.
So how do we create on of these ResourceDictionaries, well in XAML we would do the following
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > //makrup resources to be defined here </ResourceDictionary>
This would allow another XAML/code behind file to use these resources. So you can kind of think of this as the linkage step if you are from a Flash background. What well do is to create a MergedDictionary which will contain the XAML resource file. Once that step is completed the resources within the MergedDictionary may be used within code. Let see an example of how to define a MergedDictionary
<ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Dictionary1.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary>
Flash doesnt really have any layout operations such as Dock or Anchor. It doesnt have any container controls as such. Any object is simply placed right on to a canvas (the stage really). So theres not much to mention about this.
WPF on the other hand has a lot of controls which specifically deal with layout. These control are all Panels of some sort. There is StackPanel : The StackPanel lays out child elements by stacking them one after the other. Elements are "stacked" in the order they appear in the Xaml file (document order in XML terms). Items can either be stacked vertically (the default) or horizontally.
<StackPanel> <TextBlock FontSize="16" Foreground="#58290A"> Items inside a StackPanel</TextBlock> <Button>Item 2</Button> <Border BorderBrush="#feca00" BorderThickness="2"> <TextBlock>Item 3</TextBlock> </Border> </StackPanel>
<StackPanel Orientation="Horizontal"> <TextBlock FontSize="16" Foreground="#58290A"> Items inside a StackPanel</TextBlock> <Button>Item 2</Button> <Border BorderBrush="#feca00" BorderThickness="2"> <TextBlock>Item 3</TextBlock> </Border> </StackPanel>
WrapPanel : The wrap panel lays out items from left to right. When a row of items has filled the horizontal space available to them the panel wraps the next item around onto the next line (in a similar way to how text is layed out).
<WrapPanel> <TextBlock FontSize="16" Foreground="#58290A"> Items inside a WrapPanel</TextBlock> <Button>Item 2</Button> <Border BorderBrush="#feca00" BorderThickness="2"> <TextBlock>Item 3</TextBlock> </Border> </WrapPanel>
DockPanel : The DockPanel allows elements to be docked to the edges of the panel's container, similar to Windows Forms docking. Items are docked in the order they appear in the Xaml file (document order). The last Border element fills all the remaining space since no DockPanel.Dock attribute is specified for it.
<DockPanel> <TextBlock FontSize="16" DockPanel.Dock="Top" Foreground="#58290A"> Items inside a DockPanel</TextBlock> <Button DockPanel.Dock="Left">Item 2</Button> <Border BorderBrush="#feca00" BorderThickness="2"> <TextBlock>Item 3</TextBlock> </Border> </DockPanel>
Canvas : The Canvas panel is similar to the way old rich-client layout worked where you control the absolute position of things by setting a Top and Left property for them. Additionally, instead of setting the Left to position an item you can instead set the Right, or instead of setting the Top you can set the Bottom. If you specify a Left and a Right the Right value is ignored, the element does not change its size to make both these values correct, and similarly Top takes precedence over Bottom. Elements that are declared earlier in the Xaml file can appear behind elements that are declared later (if their positions over-lap).
<Canvas> <TextBlock FontSize="16" Canvas.Top="10" Canvas.Left="20" Foreground="#58290A"> Items inside a Canvas</TextBlock> <Button Canvas.Bottom="25" Canvas.Right="50">Item 2</Button> <Border BorderBrush="#feca00" BorderThickness="2" Canvas.Top="20" Canvas.Left="50"> <TextBlock>Item 3</TextBlock> </Border> </Canvas>
Grid : The Grid panel is an extremely flexible panel, and can be used to achieve almost everything that can be done with the other panel controls (although often not with the same ease). The grid panel allows you to define rows and columns in the grid using Xaml, and then place controls in calls in the grid using grid-specific attributes. Elements can span multiple rows or columns. The grid will automatically make all its rows and columns the same size (based on the size of the content) but you can specify a proportional size for rows and columns using a star notation, or specify an absolute width or height. The star notation can be seen in the example code below where one of the columns is twice the width of the other column by setting the Width attribute to "2*". The example below also shows the height of one row being set to an absolute value. The differences these introduce can more readily be seen when re-sizing the form containing the grid, as the grid will expand by default to fill the space available to it.
<Grid Margin="10" ShowGridLines="True"> <Grid.ColumnDefinitions> <ColumnDefinition Width="2*" /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="25" /> <RowDefinition /> <RowDefinition Height="2*"/> </Grid.RowDefinitions> <TextBlock FontSize="16" Foreground="#58290A" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" > Items inside a Grid</TextBlock> <Button Grid.Column="0" Grid.Row="1"> Item 2</Button> <Border BorderBrush="#feca00" BorderThickness="2" Grid.Column="1" Grid.Row="2"> <TextBlock>Item 3</TextBlock> </Border> </Grid>
In Flash MX 2004 upwards there were a whole host of new data access controls added to Flash, these are shown below

It is by using these new controls that Flash is able to perform Databinding it also has the usual controls that one would want to bind data to such as
As can be seen Flash supports DataSets / XMLConnector and WebServiceConnector. These are probably the most typical components used. Flash is a little strange in that it needs to communicate with the page that is holding the Flash object (remember Flash is Client side, the Database is server side) to grab data from the underlying database. Typically Flash would use a DataSet to bind to a DataGrid. The DataSet would be populated by an XMLConnector which hold XML data that gets populated via Flash talking to it hosting page. This could be PHP or and ASP page for example. Flash could also talk and bind directly to a web service. The 3 links below discuss each of these options in more detail should you be interested.
http://www.flash-db.com/Tutorials/databind/CatalogTutorial.php?page=5
http://www.adobe.com/devnet/flash/articles/flashpro_asp.html
http://livedocs.adobe.com/flash/mx2004/main_7_2/wwhelp/wwhimpl/js/html/wwhelp.htm
The Flash documentation is also very good, you just have to search it. The reference section at the bottom of this article contains a link to the Flash documentation.
I have to say that I think WPF has the edge on databinding. Its truly insane what you can do with databinding in WPF. You can bind a property from the following sources:
It basically quite mad. To be honest its probably a bit too much to go into in this comparison article. I would however suggest that if you want to know more about the way WPF binding works you could read the following articles
Flash doesnt have any concept of any of these quite WPF techniques. Though onw possible solution would be to use XML files to dictate Styles, Poistions, Skin Colors etc etc. Flash has excellent XML support, so this is the route I would go and have seen used.
Windows Presentation Foundation (WPF) styling and templating refer to a suite of features (styles, templates, triggers, and storyboards) that allow an application, document, or user interface (UI) designer to create visually compelling applications and to standardize on a particular look for their product. An author or designer can customize a look extensively on an application-by-application basis, but a strong styling and templating model is necessary to allow maintenance and sharing of a look. Windows Presentation Foundation (WPF) provides that model.
You can think of a Style as a convenient way to apply property values. Lets consider this small example which Styles a standard button.
<Style TargetType="Button"> <!--Set to true to not get any properties from the themes.--> <Setter Property="OverridesDefaultStyle" Value="True"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Grid> <Ellipse Fill="{TemplateBinding Background}"/> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
Which when its applied to a button results in
For most controls, there is appearance and behavior. Consider a button: appearance is the raised area that you can press, and the behavior is the Click event that gets raised in response to a click.
Sometimes, there may be a control that provides the behavior that you need but not the appearance that you need. So far, we have shown that you can use style setters to set property values to affect the look of control. However, to change the structure of a control or to set property values on the components that comprise a control, you need to use a ControlTemplate.
In WPF, the ControlTemplate of a control defines the appearance of the control. You can change the structure and appearance of a control by defining a new ControlTemplate for the control. In many cases, this gives you enough flexibility so that you don't have to write your own custom controls. If you do not define your own ControlTemplate for your control, you get the default template that matches the system theme, which is what gives the Button control its default look.
One thing to keep in mind is that once you create a ControlTemplate for you control, you are replacing the entire ControlTemplate. For example, you may define your Button ControlTemplate the following way.
<Style TargetType="ListBox"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ListBox"> <Border CornerRadius="5" Background="{TemplateBinding ListBox.Background}"> <ScrollViewer HorizontalScrollBarVisibility="Auto"> <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center" IsItemsHost="True"/> </ScrollViewer> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style>
This example defines a ControlTemplate for a ListBox
I'm going to be bit cheeky here are simply direct you to a full article on this, as the explanation is much better there. Its by Josh Smith (suprise suprise) and the link is located right here
Flash is basically a vector based animation environment, but there are options available for 3d. Most notably Swift3D which allows user to create 3D model and export straight into Flash.
WPF has good support for both vector and 3D. It has native support for 3D built into the framework. For example, lets consider a 3D button style. The code is as shown below
<!-- 3D Media Buttons --> <Style x:Key="btn3DStyle" TargetType="{x:Type Button}"> <Style.Resources> <Storyboard x:Key="Spin"> <DoubleAnimation Storyboard.TargetName="CubeRotation" Storyboard.TargetProperty="Angle" BeginTime="0:0:0" Duration="0:0:1" From="0" To="360" DecelerationRatio="0.5" AccelerationRatio="0.5" /> <DoubleAnimation Storyboard.TargetName="CubeRotation" Storyboard.TargetProperty="Angle" BeginTime="0:0:1" Duration="0:0:1" From="360" To="0" DecelerationRatio="0.5" AccelerationRatio="0.5" /> <DoubleAnimation Storyboard.TargetName="CubeScale" Storyboard.TargetProperty="ScaleX" BeginTime="0:0:0" Duration="0:0:1" From="0.5" To="0.75" /> <DoubleAnimation Storyboard.TargetName="CubeScale" Storyboard.TargetProperty="ScaleX" BeginTime="0:0:1" Duration="0:0:1" From="0.75" To="1.0" /> <DoubleAnimation Storyboard.TargetName="CubeScale" Storyboard.TargetProperty="ScaleY" BeginTime="0:0:0" Duration="0:0:1" From="0.5" To="0.75" /> <DoubleAnimation Storyboard.TargetName="CubeScale" Storyboard.TargetProperty="ScaleY" BeginTime="0:0:1" Duration="0:0:1" From="0.75" To="1.0" /> <DoubleAnimation Storyboard.TargetName="CubeScale" Storyboard.TargetProperty="ScaleZ" BeginTime="0:0:0" Duration="0:0:1" From="0.5" To="0.75" /> <DoubleAnimation Storyboard.TargetName="CubeScale" Storyboard.TargetProperty="ScaleZ" BeginTime="0:0:1" Duration="0:0:1" From="0.75" To="1.0" /> </Storyboard> </Style.Resources> <Setter Property="Width" Value="100"/> <Setter Property="Height" Value="100"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate> <ControlTemplate.Triggers> <Trigger Property="Button.IsMouseOver" Value="true"> <Trigger.EnterActions> <BeginStoryboard Storyboard="{StaticResource Spin}"/> </Trigger.EnterActions> </Trigger> </ControlTemplate.Triggers> <Viewport3D> <Viewport3D.Camera> <PerspectiveCamera Position="4,4,4" LookDirection="-1,-1,-1" /> </Viewport3D.Camera> <Viewport3D.Children> <ModelVisual3D> <ModelVisual3D.Content> <DirectionalLight Direction="-0.3,-0.4,-0.5" /> </ModelVisual3D.Content> </ModelVisual3D> <ModelVisual3D x:Name="Cube"> <ModelVisual3D.Transform> <Transform3DGroup> <RotateTransform3D> <RotateTransform3D.Rotation> <AxisAngleRotation3D x:Name="CubeRotation" Axis="1,2,3" Angle="0" /> </RotateTransform3D.Rotation> </RotateTransform3D> <ScaleTransform3D x:Name="CubeScale" ScaleX="1" ScaleY="1" ScaleZ="1" CenterX="0" CenterY="0" CenterZ="0" /> </Transform3DGroup> </ModelVisual3D.Transform> <ModelVisual3D.Content> <GeometryModel3D x:Name="OB_Cube"> <GeometryModel3D.Material> <DiffuseMaterial> <DiffuseMaterial.Brush> <VisualBrush ViewportUnits="Absolute" Transform="1,0,0,-1,0,1"> <VisualBrush.Visual> <Border Background="{Binding Path=Background, RelativeSource='{RelativeSource TemplatedParent}'}"> <Label Content="{Binding Path=Content, RelativeSource='{RelativeSource TemplatedParent}'}" /> </Border> </VisualBrush.Visual> </VisualBrush> </DiffuseMaterial.Brush> </DiffuseMaterial> </GeometryModel3D.Material> <GeometryModel3D.Geometry> <MeshGeometry3D x:Name="ME_Cube" Positions="1,1,-1 1,-1,-1 -1,-1,-1 -1,1,-1 1,1, 1 -1,1,1 -1,-1,1 1,-1,1 1,1,-1 1,1,1 1,-1,1 1,-1,-1 1,-1,-1 1,-1,1 -1,-1, 1 -1,-1,-1 -1,-1,-1 -1,-1,1 -1,1,1 -1,1,-1 1,1,1 1,1,-1 -1,1,-1 -1,1,1" TriangleIndices="0 1 2 0 2 3 4 5 6 4 6 7 8 9 10 8 10 11 12 13 14 12 14 15 16 17 18 16 18 19 20 21 22 20 22 23" TextureCoordinates="0,1 0,0 1,0 1,1 1,1 -0,1 0,-0 1, 0 1,1 -0,1 0,-0 1,0 1,0 1,1 -0,1 0, -0 -0,0 1,-0 1,1 0,1 1,-0 1,1 0,1 -0,0"/> </GeometryModel3D.Geometry> </GeometryModel3D> </ModelVisual3D.Content> </ModelVisual3D> </Viewport3D.Children> </Viewport3D> </ControlTemplate> </Setter.Value> </Setter> </Style>
which results in a normal button which shows video on its surface as a 3d cube as shown below
Flash allow uses to create almost limitless animations. We can use motion paths, create tweens, which use key frames to allow us to specify certain frames that dictate how an object will look, and the parts in between are interpolated. At key frames we can spacify size, color, position, opacity, rotation anything really.
In my mind when it comes to animations Flash wins hands down no contest not even close from anything else ever. Its the daddy, brother, sister and mother, 2nd cousin etc etc all in one. It rocks. And why is this. Well its to do with 2 reasons really.
Recall that the stage had layers down and time across. Not that great you might say. But what it does allow is the user to have different objects on the same layer at different times within the stage. For example lets say we have the following
A single layer with a square at Frame1, and a circle at Frame2
Does this seem cool yet. No you say. Well it is. This is whay. If we can have anything we like at a given frame within a layer. The object that exists at a frame can then be animated. And if we can bring in new items along the stage at any frame we want, and we consider this across all layer, and then consider that each MovieClip can have such an arrangement, and that any number of MovieClip can be brought into the main stage either manually or programaitically, we all of a sudden have a very powerful animation environment. And if that wasnt enough we can also do all this though code using a 3rd party action script that some mad guy wrote to allow user to control tweens (a fundamental Flash animation object) through action script.
All that needs to be done is that the tweening library is refernced in the main stage action script as shown below
#include "lmc_tween.as"
Each MovieClip object can then be controlled via action script, such as using the alphaTo method
MovieClip.alphaTo()
Availability
my_mc.alphaTo(alpha, seconds, animtype, delay, callback, extra1, extra2)
alpha end value ofmovieclip _alpha property
all other parameters work as in tween() method
None
Where an example might be (this is used within the BlockManager.as of FlashDemo1.zip)
tmpLoc.alphaTo(100,.1,'linear',i/20,{func:'playClip',scope:this,args:[tmpLoc]})
The 3rd party tweening library is available as a .MXP which is a Macromedia Extension file, and is officially available at the author site which is http://laco.wz.cz/tween/?page=download this site also hold the API documentation
WPF does indeed support animations. But to my mind its not a touch on Flash. The reason being that there isnt a conecpt of a stage, there is a timeline but that is only used in DoubleAnimationUsingKeyFrames. Where as Flash uses time everywhere, and you can even swap out whats shown on a layer at time(x).
To further understand what I mean, and why Flash is better, we need to understand how WPF apps are created. They are created using either XAML which is a tree type structure or by using code behind procedural code. So why is this not as flexible as Flash. Well in both cases the content of the page is not that dynamic. In the case of XAML the tree is fairly static, whats there at design time is what well get at runtime. Ok we could add new controls which we could animate in code behind, which in fact is a partial solution, but its just seems clumsy to me. We could also have different pages that are loaded one after another, or we could simply destroy the current XAML tree and load in a new XAML document tree from disk and that would offer some sort of flexibility.
I just think Flash has it better. Layers with whatever you want at any frame, and time used in all stages everywhere, and the ability to bring items to and from the stage at will. I mean serioulsy have a look at FlashDemo3.zip and see how easy you think that would be to do in WPF, let alone Silverlight which is a cutdown version of WPF anyway.
But anyway, to use animations in WPF, we can either use XAML or procedural code. Lets have a look shall we.
There are 2 options available in WPF, you can use DoubleAnimation or we could use DoubleAnimationUsingKeyFrames
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowTitle="Fading Rectangle Example">
<StackPanel Margin="10">
<Rectangle
Name="MyRectangle"
Width="100"
Height="100"
Fill="Blue">
<Rectangle.Triggers>
<!-- Animates the rectangle's opacity. -->
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:5"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</StackPanel>
</Page>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace SDKSample
{
public class RectangleOpacityFadeExample : Page
{
private Storyboard myStoryboard;
public RectangleOpacityFadeExample()
{
NameScope.SetNameScope(this, new NameScope());
this.WindowTitle = "Fading Rectangle Example";
StackPanel myPanel = new StackPanel();
myPanel.Margin = new Thickness(10);
Rectangle myRectangle = new Rectangle();
myRectangle.Name = "myRectangle";
this.RegisterName(myRectangle.Name, myRectangle);
myRectangle.Width = 100;
myRectangle.Height = 100;
myRectangle.Fill = Brushes.Blue;
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 1.0;
myDoubleAnimation.To = 0.0;
myDoubleAnimation.Duration = new
Duration(TimeSpan.FromSeconds(5));
myDoubleAnimation.AutoReverse = true;
myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;
myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);
Storyboard.SetTargetName(myDoubleAnimation,
myRectangle.Name);
Storyboard.SetTargetProperty(myDoubleAnimation,
new PropertyPath(Rectangle.OpacityProperty));
// Use the Loaded event to start the Storyboard.
myRectangle.Loaded += new
RoutedEventHandler(myRectangleLoaded);
myPanel.Children.Add(myRectangle);
this.Content = myPanel;
}
public void myRectangleLoaded(object sender, RoutedEventArgs e)
{
myStoryboard.Begin(this);
}
}
}
Is like normal animations but this time we get key frames, which is where we can say what an object will look like at time(x).
<!-- Using Paced Values. Rectangle moves between key frames at
uniform rate except for first key frame
because using a Paced value on the first KeyFrame in a
collection of frames gives a time of zero. -->
<Rectangle Height="50" Width="50" Fill="Orange">
<Rectangle.RenderTransform>
<TranslateTransform x:Name="TranslateTransform04" X="10" Y="270" />
</Rectangle.RenderTransform>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="TranslateTransform04"
Storyboard.TargetProperty="X"
Duration="0:0:10"
RepeatBehavior="Forever">
<!-- KeyTime properties are expressed with values of Paced.
Paced values are used when a constant rate is desired.
The time allocated to a key frame with a KeyTime of
"Paced"
is determined by the time allocated to the other key
frames of the animation. This time is calculated to
attempt to give a "paced" or "constant velocity"
for the animation. -->
<LinearDoubleKeyFrame Value="100" KeyTime="Paced" />
<LinearDoubleKeyFrame Value="200" KeyTime="Paced" />
<LinearDoubleKeyFrame Value="500" KeyTime="Paced" />
<LinearDoubleKeyFrame Value="600" KeyTime="Paced" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
As we have already seen Flash support the creation of custom controls, by inheriting from the standard controls. Creation of totally new controls is not really the Flash way, one would probably make a MovieClip to do a task. This would be the control. There isnt really much more to be said here.
As WPF is using .NET 3.0 Framework we can of course inherit from UserControl or Control to create new controls. We can also simply inherit and override existing control methods. Its all standard OO stuff. But its all possible. And intersting control is shown here where Cristian Graus and Nishant Sivakumar inherit from the AnimationTimeline class and get it to animate a GridLength
Like I say I am no expect in either of these fields, but this is how I would go about developing stuff for each of these worlds
Create small part that perform a specfic task. Make these as MovieClip objects, which have the correct library linkage and are exported for action scripting. Create external action script objects, try to use a OO design method. Think classes. Use the Sepi editor, its good. Keep the stage tidy.
Think about what you are trying to do, use the most appropriate method to do the job. If its XAML orientated use XAML, otherwise use code. Do use ValueConvertors, Resource files/ MergedDictionaries, Templates, Styles and dont subclass everything just cos thats what you did before in .NET 2.0.
Sub classing really isnt needed that often in WPF, you can usually do what you want with a Style or a Template. Oh and dont go overboard on the animations just cos you can. Again keep classes well defined and specific to the job they should perform.
Flash does have a fairly extensive set of classes. Lets consider the following 2 diagrams
We can see that Flash provides serveral packages, we even have some Client/Server package to deal with XML and we can also use sockets. Quite cool really for a little plugin.
Well, where do you start. WPF relies on the .NET 3.0 Framework, of which WPF is one part. The .NET 3.0 framework is vaste, and has literally 1000s of classes interfaces structures etc etc.
Shown below is a screen shot of the main WPF related packages of the .NET 3.0 framework. Using these classes a programmer is able to do all of the topics mentioned above, and of cours,e as they are simply classes, we can inherit from them and bend them to do our bidding. This is also what Macromedia (well adobe I suppose) have done with AS3 (You could inherit from other classes in AS2 as well actually). AS3 is a total rewrite and is basically very Java like syntax now, and it also allows full OO techniques to be used, not just inheritence, but method overriding, polymorphism etc etc. But this article (just cos I have Flash MX 2004) was all about AS2.
Anyway as I say heres a screen shot of the main WPF .NET framework packages. BUt expect this to grwo with future versions. Remember this is the 1st release of WPF. And also bear in mind that most of these individual pacakes will have between 10-100 different classes. Its a big framework.
What if we compare the .NET 3.0 Media package with its Flash equivalent.
There are loads more .NET 3.0 media classes than there are in Flash. But ive seen some pretty cool Flash apps. And dont forget Silverlight (WPF/e) is really the Flash equivalent, and will not have the full power of WPF to play with. It will run in a safe sandbox and will have a subset of the full WPF APIs available. So this full list of classes may not be available to Silverlight.
My personal opinion on this, is that sometimes less is more. Flash may not have it al,l but what it does have it does really really well. However one could also argue that .NET 3.0 is really just an extension to .NET 2.0 so we can use all the good .NET 2.0 stuff aswell, which indeed we can. Oh there also the small matter LINQ and generics which we can use in WPF but not in Flash. Mmm the debate goes on.
I have included 3 zip files at the top of this article, all of which show different types of flash applications, FlashDemo1.zip / FlashDemo3.zip are mainly animations with some AS2 external files, FlashDemo2.zip is more application like, and probably more in line with the sort of development one would do in a WPF application. I have not inluded a WPF application here as there are loads of finished WPF projects available both here at www.codeproject.com or just searching in www.google.com
Simply extract the zip file and open the Video.exe as ive made a nice executable for you
The zip also contains all the files to view and run the Flash application if you want to. This one is all about how to use external AS2 files and to use tweens (animations in WPF) and is a short movie to a sound track.
Simply extract the zip file and open the MMDA_Assign2.exe as ive made a nice executable for you. The zip also contains all the files to view and run the Flash application if you want to.
Is a mobile phone demo video, and offers a phone book, simulating a call, popup help, web cam usage.
This image may also be useful for you in order to see all the features demonstrated (click the image below for a bigger image)
Is an animated Flash site that I did for a HardCore techno record label I used to own and run, Surgeon 16 Recordings. My name was Dr Machette in case anyone is interested here is a discogs link to my label here and me by myself this one on a german label called SpecialForces.
Simply extract the zip file and open the S16_Launcher.html in your favourite browser. The zip also contains all the files to view and run the Flash application if you want to.
I have not included the music files with this one otherwise it would be very large download.
This one actually navigated to 5 areas, you can navigate to each of these areas using the Navigate buttons shown at the bottom. This was my first place project ever, and uses a lot of animation, so the stage is very busy. This is a good example of something that could probably be done tidier and could be refactored to use the library and linkage we talked about earlier.
I have not created any new WPF demos for this article. But I have written a few in the past, you can find those under the Windows Presentation Section of my articles
Although there is not that much code in this article, I had fun doing this one, and hope that it will be useful to someone out there.
I would just like to ask, if you liked the article please vote for it, and leave some comments, as it lets me know if the article was at the right level or not, and whether it contained what people need to know.
I hope that this article has covered the main areas of both Flash and WPF. For me I like both for different reasons, but if I was going to do a pure animation app I would use Flash, and WPF for a miore data driven application. Im going to try Silverlight next, sio ill let you know how that goes. Ill start with a simple animation app, and build from there. Anyway if you got this far well done.
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 7 Nov 2009 Editor: Sean Ewington |
Copyright 2007 by Sacha Barber Everything else Copyright © CodeProject, 1999-2009 Web15 | Advertise on the Code Project |