Showing posts with label learning. Show all posts
Showing posts with label learning. Show all posts

Friday, August 08, 2008

Expert days – last minute changes

Next week we’ll starting Expert Days, so you have a last chance to register for Windows Presentation Foundation for fellow developers (12-Aug) and Mastering Microsoft Silverlight 2.0 (13-Aug). Those sessions will take place in Bein-Thumi Herzeliya and start in 8:30.

We have not enough participants to open Advanced .NET 3.5 SP1 (14-Aug) [not enough people know WPF so far in Israel?], thus I would like to propose another kind of session – something like we used to do in Dev Days. You’ll come with your WPF applications, prepare to ask questions about problems with those apps and we’ll solve it together during the day. I will not have slides for this session – it will be live QnA+Discussions meeting. This specific session will take place in Megamot college in Petah-Tikva (not in Bein-Thumi, like all others). What do you think?

Last notice, if we will not have at least 26 attendees (currently for this session we have only 10), neither Advanced .NET 3.5 nor WPF QnA will be opened. Also, all people registered for those sessions will be refunded. So, now you will choose whether and which session about WPF we will open Thursday next week.

Tuesday, July 08, 2008

How to handle thickness

Yesterday, we spoke about type converters. We even, built simple generic enum converter. Today, we’ll create more complicated converter, that very missing in Silverlight – ThicknessConverter. During the post, I also explain about tokenizing values in Silverlight

image

What is Thickness ?

What is thickness in Silverlight? It’s

<Border BorderThickness=”6”/>

or

<Border BorderThickness=”6,4,3,2”/> or <Border BorderThickness=”6, 4, 3,2”/> or, even <Border BorderThickness=”6; 4; 3 ;2”/>

How to handle it?

Tokenizing strings

What you seen here is tokenized strings. We have to split them by known token (one and own for each string) and then we can parse it for converter. How to do this? Complicated – too much cases. But, basically, you have to get string, quote character and separator. Don’t forget to check for empty spaces

private void Initialize(string str, char quoteChar, char separator)
        {
            this._str = str;
            this._strLen = (str == null) ? 0 : str.Length;
            this._currentTokenIndex = -1;
            this._quoteChar = quoteChar;
            this._argSeparator = separator;
            while (this._charIndex < this._strLen)
            {
                if (!char.IsWhiteSpace(this._str, this._charIndex))
                {
                    return;
                }
                this._charIndex++;
            }
        }

Then we have to scan string to find tokens

private void ScanToNextToken(char separator)
        {
            if (this._charIndex < this._strLen)
            {
                char c = this._str[this._charIndex];
                if ((c != separator) && !char.IsWhiteSpace(c))
                {
                    Exceptions.ThrowInvalidOperationException("No Separator Found");
                }
                int i = 0;
                while (this._charIndex < this._strLen)
                {
                    c = this._str[this._charIndex];
                    if (c == separator)
                    {
                        this._foundSeparator = true;
                        i++;
                        this._charIndex++;
                        if (i > 1)
                        {
                            Exceptions.ThrowInvalidOperationException("Empty Token Found");
                        }
                    }
                    else
                    {
                        if (!char.IsWhiteSpace(c))
                        {
                            break;
                        }
                        this._charIndex++;
                    }
                }
                if ((i > 0) && (this._charIndex >= this._strLen))
                {
                    Exceptions.ThrowInvalidOperationException("Emply Token Found");
                }
            }
        }

why not just split? Because it is not generic solution for strings with empty tokens, which is absolutely invalid. Another reason of using such helper is performance. String operation are not very fast things, thus we’ll check only the number of tokens required for future operations.

Also, we should make sure, that all tokens are required and get rid of unnecessary parts of the string, such as leading spaces, control characters etc. Now, when we have tokenized string, we can start building converter

Building thickness converter

Actually, the most significant part of this converter is tokenization , thus the most important override method for such converter is ConvertFromString

public override object ConvertFromString(string text)
        {
            Thickness res = new Thickness();
            TokenizerHelper helper = new TokenizerHelper(text);
            double[] numArray = new double[4];
            int index = 0;
            while (helper.NextToken())
            {
                if (index >= 4)
                {
                    index = 5;
                    break;
                }
                LengthConverter lc = new LengthConverter();
                numArray[index] = (double)lc.ConvertFromString(helper.GetCurrentToken());
                index++;
            }
            switch (index)
            {
                case 1:
                    res = new Thickness(numArray[0]); break;
                case 2:
                    res = new Thickness(numArray[0], numArray[1], numArray[0], numArray[1]); break;

                case 4:
                    res = new Thickness(numArray[0], numArray[1], numArray[2], numArray[3]); break;
                default:
                    typeof(Thickness).ThrowConvertFromException(text); break;
            }
            return res;
        }

The only thing to remember is to check whither we can convert from the type received from XAML

public override bool CanConvertFrom(Type sourceType)
        {
            switch (Type.GetTypeCode(sourceType))
            {
                case TypeCode.Int16:
                case TypeCode.UInt16:
                case TypeCode.Int32:
                case TypeCode.UInt32:
                case TypeCode.Int64:
                case TypeCode.UInt64:
                case TypeCode.Single:
                case TypeCode.Double:
                case TypeCode.Decimal:
                case TypeCode.String:
                    return true;
            }
            return false;
        }

Have a nice day and be good people. Stay tuned for future work process items.

Monday, June 30, 2008

Printouts of the slides, presented on Silverlight 2.0 open house today

Thank you all, who participated today in Silverlight 2.0 for building Rich Internet Applications event. I uploaded printouts of the slides, presented during the session here. So, you can download it for reference.

I’m really interesting within your feedback (leave comments) in order for me to be able to enhance it for future events.

Also, I want to remind you, that due to lack of space we were unable to handle all those who want to attend, thus we decided to make another session within two weeks, so can register here. Remember, only registered attendees, who with confirmation received will allow to enter. So, hurry up.

If you want to learn more about Silverlight, you can register to attend Expert Days “Mastering Microsoft Silverlight 2.0 – 020 full day course, 13-August, were we’ll have Silverlight 2.0 deep dive training day. You can also review another two courses, I’ll have there:

Download slides from today session >>

Register to attend next event at 23 July >>

image

Thank you and leave a comment…

Sunday, June 29, 2008

Silverlight 2.0 for building Rich Internet Applications (Local Event) – Take 2

As promised earlier, the next session of Silverlight 2.0 for building Rich Internet Applications will take place at 23 July, 8:30 AM-12:30 PM in ILDC. This is exactly the same session for those, who unable to attend tomorrow due to lack of place.

Please, this time, try to register as soon as possible to assure seat assignment.

Register to attend Silverlight 2.0 for building RIA >>

Monday, April 14, 2008

My TechEd ‘08 presentation slides download

I do not know why, but for some reason in development section of TechEd website there are only two recording and no presentations. I do not want to wait for them to upload (we sent all presentations a while ago), so here it comes. My TechEd presentation DEV335 - Game Development Using Microsoft’s Latest Technologies. I have no recordings by now (so pity), so you’ll have to wait for Microsoft to encode and upload it. Upon it will be done, I’ll publish it here.
There is no real reason to upload samples – they will not work without all environment we had there.

Download full slides from my TechEd presentation (PPT 7,165 KB) >>

If you have any questions, feel free to contact me by using contact form or LinkedIn profile. You also can send me a message by twitter

te08

Sunday, April 13, 2008

How to have more, then one forms in page and be able to submit it to server without page refresh using ASP.NET AJAX

Someone asked me in Meet an Expert lunch in TechEd about having more, then one server forms in one page, using ASP.NET AJAX. The answer was simple – make only one visible at one time. Other words, hide all and show only one relevant

<script runat=server language="C#">
private void Page_Load(object sender, System.EventArgs e)
{
Form1.Visible = !Form1.Visible;
Form2.Visible = !Form2.Visible;
}

<form id="Form1" runat="server" >…
<form id="Form2" runat="server" visible="false">…



That’s all. However, what to do if you need to show them all? Let’s try to understand. First of all, let’s make them client based




<form id="form1" >…

<form id="form2" >…




Then we should handle onsubmit method and neutralize it, before the page will be reloaded (we do not want reloads – AJAX rulez!)




<form id="form1" onsubmit="onSubmit(this); return false;">…

<form id="form1" onsubmit="onSubmit(this); return false;">…




So, the final code will looks as following (there are some of such forms):




<form id="form1" onsubmit="onSubmit(this); return false;">

    <div>


    <h2>Client Form 1</h2>


    <input type="text" id="val" />


    <input type="submit" value="Submit 1" />


    </div>


    </form>




Then, let’s have one server side form, that will handle our requests




<form runat="server">

<asp:Label ID="Result" runat="server"/>




And now, let’s submit our results there. Yes, we can access server side controls from client side JavaScript




<script type="text/javascript">

       function onSubmit(sender)


       {


            var what = sender["val"].value;


            if(what == "")


                what = "nothing";


            $get("Result").innerHTML=sender.id+" tells you "+what;



       }




Well, but as you, probably understand, there is no real submit was performed. We need client-server-client roundtrip in order to do it. What to do? The answer is PageMethods.



Let’s add simple page method, that formats the string and added time tag




<script runat="server">

            [System.Web.Services.WebMethod]


            public static string UpdatePanel(string senderID, string what)


            {


                return string.Format("{0} tells you {1} at {2} with server roundtrip", senderID, what, DateTime.Now);


            }


       </script>




One we have such. All we have to do is to enable page methods by using ScriptManager




<form runat="server">

    <h2>Result</h2>


        <asp:ScriptManager runat="server" EnablePageMethods="true" />


        <asp:Label ID="Result" runat="server"/>


    </form>




And then, call it from javascript




function onServerSubmit(sender)

       {


            var what = sender["val"].value;


            if(what == "")


                what = "nothing";


            PageMethods.UpdatePanel(sender.id,what,onServerSubmitCompleted);



       }

function onServerSubmitCompleted(value)


       {


         $get("Result").innerHTML=value;


       }




We done. BTW, if we’ll try to pass HTML object into server, we’ll get "Cannot serialize object with cyclic reference within child properties" exception – this is not bug, this is warlock for bad HTML programmers. If you want to be able to pass whole form (HTML object) into server you’ll probably have to either use LosFormatter, or any other custom HTML serializer to do it.  Want to know more about it? Maybe another time.



Have a nice week and be good people.



Source code for this article

Tuesday, March 25, 2008

FindResource replacement and how to change control style more then once in Silverlight 2.0 application

As deeper we’re digging in Silverlight 2.0, we finding more and more WPF things and we’re really missing in Silverlight. One of such things is FindResources.

In WPF I had Visual and Logical tree, so I was able to travel the tree to find resource I need. Let’s see an example of the application. We have one resource defined in App level

<Application.Resources>
        <Style TargetType="Button" x:Key="green">
            <Setter Property="Background" Value="Green"/>
        </Style>
</Application.Resources>

Another resources are defined in different levels of Page

<UserControl.Resources>
        <Style TargetType="Button" x:Name="red">
            <Setter Property="Background" Value="Red"/>
        </Style>       
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.Resources>
            <Style TargetType="Button" x:Name="blue">
                <Setter Property="Background" Value="Blue"/>
            </Style>
        </Grid.Resources>
        <Button Content="Click me" Click="Button_Click">
            <Button.Resources>
                <Style TargetType="Button" x:Name="yellow">
                    <Setter Property="Background" Value="#FFFFFF00"/>
                </Style>
            </Button.Resources>
        </Button>
    </Grid>

Now I want to call FindResource(“red”) and have my style ready for apply. I should not thing a lot about where the resource exists. There is no such method in Silverlight. If so, let’s see what we have. Looking in debugger I can find all my resources as members of the page.

image

But how to get them out? In Silverlight FrameworkElement, we have handy method named FindName. That’s exactly what we need. But how to get Application resources? Simple. Just look into it’s collection. Now, I can write small method, that help me to find resources in any level of Silverlight application.

public static object FindResource(string name)
        {
            if (App.Current.Resources.Contains(name))
            {
                return App.Current.Resources[name];
            }
            else
            {
                FrameworkElement root = App.Current.RootVisual as FrameworkElement;
                return root.FindResource(name);
            }
        }
        internal static object FindResource(this FrameworkElement root, string name)
        {
            if (root != null && root.Resources.Contains(name))
            {
                return root.Resources[name];
            }
            else
            {
                try
                {
                    return root.FindName(name);
                }
                catch { }               
            }

            return null;

Well now we can find all our resources. Let’s apply it to elements

Style s = (Style)Helper.FindResource("red");
b.Style=s;

It works perfect. Let’s take another one

Style s = (Style)Helper.FindResource("blue");
b.Style = s;

image

What is it? “Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))”. Why this happens only after applying second style? Let’s look into MSDN: “Styles are write-once in Silverlight. You can set a style to override a built-in default style, but attempting to set the same style again will result in an exception.”

What to do? We just have to write our own multi-use styling engine. First of all, we should get all setters of the style

foreach (Setter setter in value.Setters)

Then check target type and set values of setters to appropriate properties.

Type targetType = parent.GetValue(setter.Property).GetType();
parent.SetValue(setter.Property, setter.Value);

Another exception. That’s the mess? All values are strings. I need real values and I have no parsers. Fortunately, we have handy .NET method Convert.ChangeType. Let’s use it. Exception. Let’s check if the type is IConvertible (such as int, double, etc)

if(targetType is IConvertible)
            {
                return Convert.ChangeType(source, targetType, CultureInfo.InvariantCulture);
            }

No exception, but also no result. We need SolidColorBrush and we have only Color name, which is string. How to convert such string into Color instance and then into SolidColorBrush? The answer is reflection. We should write our own FromString converter. First of all let’s capitalize the string

static string Capitalize(this string str)
        {
            if (str.Length > 0)
            {
                return string.Concat(str.Substring(0, 1).ToUpper(), str.Substring(1, str.Length - 1));
            }
            return str;
        }

Then check whether I have static member with the same name in Colors class (not by hand of cause)

MemberInfo[] infos = typeof(Colors).GetMember(color.Capitalize());

If I have, let’s invoke it

if (infos.Length > 0)
            {
                return (Color)typeof(Colors).InvokeMember(color.Capitalize(), BindingFlags.Static | BindingFlags.Public | BindingFlags.GetProperty, null, null, null);
            }

Well done. Now we can use strings which have names of colors and convert them into real color. But what to do with not “well known colors”? Parse it

else if (color.IndexOf('#') == 0)
            {
                return Color.FromArgb(
                    byte.Parse(color.Substring(1, 2), NumberStyles.HexNumber),
                    byte.Parse(color.Substring(3, 2), NumberStyles.HexNumber),
                    byte.Parse(color.Substring(5, 2), NumberStyles.HexNumber),
                    byte.Parse(color.Substring(7, 2), NumberStyles.HexNumber));
            }

We done. Just write another attached method and use in in our converter

internal static Color ParseKnownColor(string color)
        {
            MemberInfo[] infos = typeof(Colors).GetMember(color.Capitalize());
            if (infos.Length > 0)
            {
                return (Color)typeof(Colors).InvokeMember(color.Capitalize(), BindingFlags.Static | BindingFlags.Public | BindingFlags.GetProperty, null, null, null);
            }
            else if (color.IndexOf('#') == 0)
            {
                return Color.FromArgb(
                    byte.Parse(color.Substring(1, 2), NumberStyles.HexNumber),
                    byte.Parse(color.Substring(3, 2), NumberStyles.HexNumber),
                    byte.Parse(color.Substring(5, 2), NumberStyles.HexNumber),
                    byte.Parse(color.Substring(7, 2), NumberStyles.HexNumber));
            }
            return Colors.White;
        }
……

else if(targetType == typeof(SolidColorBrush))
            {
                return new SolidColorBrush(ParseKnownColor(source));
            }

Now you turn to continue with string to object convention for your own need. Starting today you know how to do it.

Here the result

Have a nice day and be good people

Source code for this article>>

Sunday, March 02, 2008

How to: High performance graphics in WPF

Microsoft DPE: "WPF is ever best super performance oriented technology for creating hyper multi point graphs, using parallelism and huge in-memory persistence vector scrounged math distributed calculations... And ever more with branded new Microsoft Windows Vista 7.

Client: Errr, well.... Let's try to apply it for our VB program...

DPE: You can easily do it yourself, but it'd be better to call someone from Microsoft Consulting Services.

Client: Let it be...

MCS: Well. It's too huge for WPF to scale... WPF uses a retained rendering system. It saves every little pixel and make you able scale and repaint very often without the composition system blocking on callbacks to your code. However, 1,000,000 retained pixels is too huge to scale...

Client: I want it scale. They promised... They told, it'll scale. Make it to do what I want it to do!!!

MCS: Errr, well. Let it be!

This is very common dialog between DPE, MCS and clients. Sales men want it to do, what he need it to do. Client want it to do what sales men promised to do and Services men should make it to do what they both want it to do. Today we'll speak about retained, lazy and loose models to produce large scale graphics.

First problem: multithreading

Even before we start to work, you should know, that we cannot create dependency objects in thread other, then current UI thread. We can use locks, mutexes, semaphores, however we still can not create Dependency Objects in other thread. In order to get rid of it, we'll have to use INofityPropertyChanged implementation, instead of Dependency Objects. This means, no Dependency Properties.

So, we'll start with following code (I'll reuse nice code written by Luis Diego Fallas to create Mandelbrot Fractal set)

class FractsCollection : INotifyPropertyChanged
    {

Second problem: rendering thread

Well, the problem is knows. There is only one UI thread. We wont it be only one, so we'll use our own HostVisual by Dwayne Need to enhance the performance.

Third problem: Retained objects

Actually, this is not problem. This is feature. And it can be extremely useful if you want to retain layout. Let's create a simple example: Dragon curve fractal. It has limited number of points, generated by well known final algorithm. So, we'll create our own geometry, derived from Shape class. The fasted geometry is StreamGeometry, so let's use it. First of all let's create the class and save the array of points.

public class DragonShape:Shape
    {
StreamGeometry dragonGeometry;
        double _angle;
        List<Point> Points;

Then we'll generate the pattern

void GeneratePattern()
        {
            ThreadPool.QueueUserWorkItem(delegate
            {
Move(5);
Turn(GetNextPoint * System.Math.PI / 180.0);

Then, by overriding DefiningGeometry property, create the fractal

protected override System.Windows.Media.Geometry DefiningGeometry
        {
            get { 
                using (StreamGeometryContext context = dragonGeometry.Open())
                {
                    context.BeginFigure(Points[0], false, false);
                    context.PolyLineTo(Points, true, false);
                }
                return (Geometry)dragonGeometry.GetAsFrozen();}
        }

Don't forget to tell the shape, that geometry was changed

this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Background, (SendOrPostCallback)delegate
                    {
                        this.InvalidateVisual();
                    }, null);

Now, run it and we'll have very nice vector fractal generated that can be easily resized and scaled. Here the result.

image image

This method will work fine for 1,000, even 10,000 points. But after a while you'll experience performance degradation. What to do? The client wants 10,000,000 (!) points (and in Winforms GDI+ it works for him)

Let's try to understand why. Because it is not retain. It's image! So, let's use image to make the play fair.

The fastest BitmapSource is InteropBitmap. It has an ability to update itself from the memory section. That's exactly what we'll use

format = PixelFormats.Bgr32;
            max = format.BitsPerPixel;
            uint count = (uint)(sWidth * sHeight * format.BitsPerPixel / 8);
            section = CreateFileMapping(new IntPtr(-1), IntPtr.Zero, 0x04, 0, count, null);
            map = MapViewOfFile(section, 0xF001F, 0, 0, count);
            pixels = new byte[count];
            Marshal.Copy(pixels, 0, map, (int)count);
            source = System.Windows.Interop.Imaging.CreateBitmapSourceFromMemorySection(section, (int)sWidth, (int)sHeight, format, (int)(sWidth * format.BitsPerPixel / 8), 0) as InteropBitmap;
            ThreadPool.QueueUserWorkItem(delegate
            {
                while (true)
                {
                    Generate();
                }
            });

To get the source to bind to we'll get frozen image. Call Invalidate first to reread the source.

InteropBitmap source;
        public BitmapSource Source
        {
            get
            {
                source.Invalidate();
                return (BitmapSource)source.GetAsFrozen();
            }
        }

Now, when we ready to display we can just put pixels simultaneously (by using Parallel extension and PLINQ) and tell the WPF that our count and ImageSource property updated upon each pixel.

unsafe
            {
                uint* pBuffer = (uint*)map;
                Parallel.For(0, (int)sHeight, delegate(int yi)
                {
                    foreach (var p in from xi in Enumerable.Range(0, (int)sWidth).AsParallel()
                                      let mappedX = xF(xi)
                                      let mappedY = yF(yi)
                                      let p0 = new TranslatePoint(xF(xi), yF(yi))
                                      let function = constructor(p0)
                                      select new
                                      {
                                          x = xi,
                                          y = yi,
                                          xD = mappedX,
                                          yD = mappedY,
                                          i = apply(function, p0)
                                                  .TakeWhile(
                                                     (x, j) => j < max && x.NormSquared() < 4.0)
                                                  .Count()
                                      })
                    {
                        pBuffer[(int)(p.x + p.y * sWidth)] = (uint)(uint)((uint)0xFF << 24) |
                             (uint)(p.i << 16) |
                             (uint)(5*p.i << 8) |
                             (uint)(15*p.i); ;
                        count++;
                        FireUpdate();
                    }
                });
            }

void FireUpdate()
        {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("PixelCount"));
                    PropertyChanged(this, new PropertyChangedEventArgs("Source"));
                }
        }

We done. Now let's see how fast it can be to generate and display 10,000,000 live pixels (it's about 16,000x16,00x32bit image) in screen. The maximum, I was able to get with my Dell Latitude D820 was 1,200,000 x 1,200,000 pixels indexed 4 bit image (it's about 100,000,000 points) and my memory is over :)

Not bad, ah? So WPF scales and DPE are right? Not quite right, but let them to do their work and we'll be behind to come all client's dreams (and DPE's promises) true.

Have a nice day and be good people. Now you can use WPF for drawing big number of points.

Thursday, February 21, 2008

7 XNA community games for XBOX are free now!

Xbox Live Community Games is new program, announced by XNA Creators Club. It gives you a chance to download for free seven games for XBox absolutely free.  So, what are you waiting for? Download it now from http://creators.xna.com website.

What's included?

  • The Dishwasher: Dead Samurai
  • JelloCar
  • Little Gamers
  • Proximity HD
  • Rocketball
  • TriLinea
  • Culture

You can either watch an "XBox insider" video to learn how to download and run those games.

However, the most interesting news, is that Microsoft deciding be become an authority for distributing community games via Xbox Live Marketplace, thus now, you can write not only for yourself, but wider your game distribution with Microsoft.

So what are you waiting for? Download and install XNA Game Studio 2.0, come to my presentation in TechEd '08 to learn how to do it and begin to make your own gaming business (or do it just for your fun).

image

Friday, February 15, 2008

Internet safety day and Red Fish Soup

A couple of days age, there was the Internet Safety Day in Israel (for some reason nothing about it in official government website, so last year news). I begun to think, what websites can be useful for my kids? Hop tv-channel web site is pretty nice, but it teaches nothing our kids. Tipo is absolutely unuseful. There are more? Not exactly...

After some research, I found great french web site, named Poisson Rouge (Red Fish Soup). This how should build web for kids. Shame to all locals...

image

Thursday, February 07, 2008

Oh, baby, C++ is dead (at least in MS Learning)

From the very beginning, all MS Learning exams were delivered in C++ only. Later come C# and VB (.NET) and you were able to choose one of those three languages (for .NET related dev exams). Starting today, for all new exams, you'll be able to choose from only two languages- C# and VB.NET. The reason is  3 exams in C++, related of thousands in VB and C#. C++ development is still focusing mainly on native... Is it? You should not know C++ anymore? As for me, too pity... Almost no one of new developers knows C++ and it's too bad for us and even worth for whole industry!

image

Wednesday, February 06, 2008

How to build cool games by using XNA framework

This TechEd, me and Alex will explain how to make XNA, WPF and {censored} work together to develop entertainment stuff easier. In spite of the fact, that we'll explain a little about XNA core, it makes cense (if you want to know) to learn it yourself.

Trust me, XNA is brilliant framework, that makes you able to build games easier. You have not know DirectX or C++ in order to build your own WoW, Resident Evil, GTA or Halo. All you have to do is to visit XNA.com, download XNA Game Studio 2 and start programming your own game, that will run on your PC and XBOX.

Already done it and still do not know how to start? Let Dan to teach you. Visit his great video series about XNA development. Still frustrated and want to know more? Come and s ee me at TechEd'08 Eilat.

image

Friday, January 25, 2008

RTFM - Not only software needs manual, kids need it too - How to care your child (visual instructions)

For all my friends, become fathers and mothers within last couple of months. Please, read it before using your kids!

kidcare kidcare (2) kidcare (3) kidcare (4) kidcare (5) kidcare (6) kidcare (7) kidcare (8) kidcare (9) kidcare (10) kidcare (11) kidcare (12) kidcare (13) kidcare (14) kidcare (15) kidcare (16) kidcare (17) kidcare (18) kidcare (19) kidcare (20) kidcare (21) kidcare (22) kidcare (23) kidcare (24) kidcare (25) kidcare (26) kidcare (27) kidcare (28)

Thursday, January 24, 2008

SVG vs. Silverlight head-to-head fight

Adobe stops supporting SVG next year, thus there are some SVG consumers are looking for the replacement of this technology, by other, that will be supported. The only technology, can actually replace SVG is Silverlight. Yes, Flex, too, but it's too complicated to perform transitions. Today, we'll look into those two technologies and try to understand how to perform migration easily. Let's start from SVG (Adobe SVG 3.x) vs SL (Silverlight 1.0) syntax

SVG

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/SVG/DTD/svg10.dtd">
<svg width="200" height="100">
</svg>

SL

<Canvas  xmlns="http://schemas.microsoft.com/client/2007"
  Width="200" Height="100">
</Canvas>

Looks pretty the same, no? At least, very similar. Let's see what's going with text.

SVG

<text x="10" y="15" font-size="12">
  Hello World!
  <tspan x="10" dy="1.6em" font-size="8">This is</tspan>
  <tspan x="10" dy="1.6em" font-size="20">SVG text</tspan>
</text>

SL

<TextBlock Canvas.Left="10" Canvas.Top="15" >
  <Run Text="Hello World!" FontSize="12"/>
  <LineBreak/>
  <Run Text="This is" FontSize="8"/>
  <LineBreak/>
  <Run Text="Silverlight text"  FontSize="20"/>
</TextBlock>

Similar too, but what's about rendering? From now and on, you'll need Silverlight 1.0 and SVG 3.x plugins in order to see working samples.

Let's look closer

image

And even more closer

image

Silverlight renders small and large text much better, then SVG do.

Our next station is splines and simple geometry.

SVG

<rect width="100" height="50" fill="blue" stroke="black"  stroke-width="3" x="0" y="0"/>

SL

<Rectangle Width="100" Height="50" Fill="Blue" Stroke="Black" StrokeThickness="3" Canvas.Left="0" Canvas.Top="150" />

That's look very similar. What's about lines?

SVG

<path fill="white" stroke="black" stroke-width="2" d="M20,140 Q100,20 100,140 Q100,220 180,140" />

SL

<Path Fill="White" Stretch="Fill" Stroke="Black" StrokeThickness="2" Data="M20,140 Q100,20 100,140 Q100,220 180,140"/>

That's the same. Even coordinates and tangents are equal. So, how it renders?

image

Well. There are some differences here.

Never mind, let's go on into animations

SVG

<circle cx="200" cy="150" r="40" fill="red">
    <animate attributeName="cy" dur="5s" repeatCount="indefinite" keySplines="0.5 0.1 0.9 0.5;0.1 0.5 0.5 0.9" calcMode="spline" keyTimes="0;2.5;5" values="150;350;150"/>
  </circle>

SL

<Ellipse Width="80" Height="80" Fill="Red" Canvas.Left="160" Canvas.Top="-91" x:Name="ellipse">
    <Ellipse.Triggers>
        <EventTrigger RoutedEvent="Canvas.Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.Y)" RepeatBehavior="Forever">
                        <SplineDoubleKeyFrame KeyTime="00:00:02.5" Value="200" KeySpline="0.5 0.1 0.9 0.5"/>
                        <SplineDoubleKeyFrame KeyTime="00:00:05" Value="0" KeySpline="0.1 0.5 0.5 0.9"/>
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Ellipse.Triggers>
    <Ellipse.RenderTransform>
        <TransformGroup>
            <TranslateTransform/>
        </TransformGroup>
    </Ellipse.RenderTransform>
</Ellipse>

Here, it looks like a lot of differences, however, if you'll look into code, you'll see, that there are no difference between the methods. Even key splines are the same. Let's look deeper into code.

SVG SL
circle Ellipse
animate DoubleAnimationUsingKeyFrames
cx,cy Width, Height
attributeName TargetName+TargetProperty
dur KeyTime
repeatCount RepeatBehavior
keySplines KeySpline+KeySpline
calcMode SplineDoubleKeyFrame
keyTimes KeyTime+KeyTime
values (absolute) Value (relative)

 

That's all. After all, there are very similar methods and objects are in use. The only difference, that Silverlight is much more flexible, then SVG in animation. Let's see the result (if the ball is breaking on the edge, just reload internal page - this is load time issue)

So, after all if you know SVG, you can start developing Silverlight (don't go back :) ).

All this nice, but what's the problems? Well, there are some. In Silverlight 1.0, there is no Tile or Visual brushes, thus you can not create following effect (this is checker board)

SVG

<defs>
<pattern id="P01" width="10" height="10" patternUnits="userSpaceOnUse">
    <rect width="10" height="10" fill="#FFFFFF" stroke="#000000" stroke-width="0.1"/>
</pattern>
</defs>
<rect x="0" y="0" width="400" height="400" fill="url(#P01)"/>

But no worry, you probably, will have all you need and much more in Silverlight 2.0 :)

Have a nice day.

Monday, November 19, 2007

Visual Studio 2008 new test features

Referring my disappointment from the topics on 70-552, I start looking on new test features, provider by Visual Studio 2008. I worked with performance analyzer in VS2005 (which is looked much more like debug tools for .NET CLR developers in MS) and today, after public release of VS2008, I can show you my research.

From the first sight, it looks like nothing changed

 

image

But when we're digging deeper, we discover new interesting features.

image

Look in this. My application decodes jpegs most of the time. And this is very right.

image

Another great feature, that makes our live easier is Set Root method and Hot Path marking. Now, once, you found the root of your application, you're able to "hide" unnecessary nodes (in most cases, those are system calls) and then mark the critical path (from performance point of view) in your call tree. You also can find all modules and functions, called selected method.

image

Another feature of new performance analysis tool is ability to compare your test run samples.

image

Very very cool tool, however it still too complicated for average user to understand what all those numbers mean, even with handy new Noise Reduction filters :)

image

Now you, probably, know what the problem with CarKiosk.exe application. You do not know what is it? Come and see at Developer Academy II at DEV 411.