Thursday, June 12, 2008

Another Radial Panel

A few weeks back I did a post(s) on panels using Robby's animating panel base including a Radial panel. Jobi a friend of mine did a post on his radial panel he wrote so I thought I would share that with everyone. Jobi's post gets more into explaining the math where I just showed so I thought it would be interesting if your into Silverlight Panels.

http://jobijoy.blogspot.com/2008/04/simple-radial-panel-for-wpf-and.html

Wednesday, June 11, 2008

DR. WPF on Pixel8

for those that know dr. WPF. good guy I might add not that I know is super secret identity or anything... check out the pod cast at:

http://pixel8.infragistics.com/#Episode:9035

Beta 2 and Hacking the DOM

So Beta 2 is live now. finally :) and life is good. I did have a few issues getting it running but thats what happens when you use daily builds between releases... I'm building this 'video showcase app' in silverlight for a here to be annouced group at MS and need to interact with all their old bits they build around flash... One of the issues is that they pass the data and a collection of objects and instead of passing the base JSONthey map the data and process it into this collection to pass into the 'showcase'. At first I went down the JSON road and since they wouldn't pass in the JSON or lest me call the service directly this turned out to be problematic. Using ScriptObject I could get to values and properties but how do you work with a collection in javascript from silverlight...

As intensely intuitive as it seems besides using GetProperty off of an instance of ScriptObject for properties I can also use it to grab collection items so that means something like this works:

(ScriptObject)SomeChild = (ScriptObject)foobar.getProperty("0");

basically I can pass in an indexer as if it was a property and actually get a reference to that element. Personally I have mixed feelings about this but it works. And I don't have to do script injection or some other weird ness to make it work.

Tuesday, June 3, 2008

Crossfader At TechEd

Aw My lifes work is imortalized for 5 minutes in Bill G's teched presentation.

check out the pictures at:

http://www.facebook.com/album.php?aid=38501&l=1b348&id=721326429


off the web:

http://www.microsoft.com/techedonline/default.aspx

Live Tech·Ed NA Developers Keynote delivered by Bill Gates Tuesday, June 3, 2008, 8:30–10:00am EST What better way to kick off this year’s first premier technical education conference, Microsoft Tech·Ed North America 2008 Developers, than with Bill Gates, Microsoft Chairman. Join us to hear and learn about the vision of the IT industry in the years to come. High Medium Low

Monday, June 2, 2008

More on Panels

I was playing around and made a few more panels. Lets start with a random panel. This panel builds on what we learned about the animating panel base and allows us to layout everything out randomly on screen. This is especially interesting for doing graphics randomly placed around the UI and is more for effect then what you would use in a real business application. A logical use for this might be a portfolio or other like function or just for fun. If we start with the Animating Wrap Panel we need to redo the arrange method starting with replacing the variables at the top with the following:

double Width = 0;
double Height = 0;
Random ThisNum = new Random();

Like the Wrap Panel we still need to run through all the panel children. Our loop should have its internal code replaced with the following:

Width = element.DesiredSize.Width;
Height = element.DesiredSize.Height;

double NewX = double.Parse(ThisNum.Next(
int.Parse(this.Width.ToString())).ToString());
double NewY = double.Parse(ThisNum.Next(
int.Parse(this.Height.ToString())).ToString());

if (MyFirstTime)
{
SetElementLocation(element, new
Rect(NewX, 1500, Width, Height), false);
}
else
{
SetElementLocation(element, new Rect(NewX, NewY, Width, Height));
}

In this case we see that we are creating new Random X,Y values so that our layout is unique every single time. We then like the other panels call the SetElementLocation in like manner. Other wise this panel is much the same as the others.

This panel allows us more interesting possibilities now we will address one more common panel that you might want to use and animate

Animating Radial Panel

So starting with the radial panel we need to do a little more math then the others. Building this panel we add 3 variables to the class itself like this listing:
protected void GetListOfPoints(int pointCount, double Width)
{
double x = Width / 2;

Radius = x;

double y = 0;

double theta = (2 * Math.PI) / pointCount;

for (int i = 0; i < pointCount; i++)
{
if (i > 0)
{
x = (Radius * (Math.Cos((i) * theta)));
y = (Radius * (Math.Sin((i) * theta)));
}

XList.Add(x + Radius);
YList.Add(y + Radius);
}
}

With out getting into great detail this method basically gives the points we need to layout our children on. Now we can alter the arrange override and we are good. In the arrange we start with variables like this:

double Width = 0;
double Height = 0;

GetListOfPoints(this.Children.Count, this.Width );
int Count = 0;

Width = element.DesiredSize.Width;
Height = element.DesiredSize.Height;

if (MyFirstTime)
{
SetElementLocation(element, new
Rect(XList[Count], 1500, Width, Height), false);
}
else
{
SetElementLocation(element, new
Rect(XList[Count], YList[Count], Width, Height));
}

Count++;The rest of the method is the same once we drop out of the loop like the wrap panel. In this case the biggest difference in the loop is having to track our position so we can get the right X/Y values for the layout.

By default like the other panels we did using the animating panel base we start be animating the children from off the screen below. All of these panels are included in the panel factory download off of HackingSilverlight.net. With that you can do all the hot panels you like.

http://www.hackingsilverlight.net/samples/PanelFactory.zip

Friday, May 30, 2008

Animating Panels and the Animating Panel Base

One of the cool things that enhances UX (User Experience) with an application is to make it pleasing to look at and use. Many times people do searches and expect recordsets. Frequently these recordsets are placed in data grids of some kind. Though Silverlight does in fact support a data grid control we might also consider using a custom panel that lays out elements visually and to make it more excited we can animate children into position depending on the current state. Writing this so it animates nicely programmatically can be a lot of work not to mention a huge pain and not very reusable. But alas you are more than welcome to do all this extra work just to discover you should have used a dispatch timer and not use Silverlight animations altogether and then waste more time figuring out how to make that work. OR you can use the animating panel base that has the dispatch timer infrastructure written tested and built in. Robi wrote this control and gave it to Mike H were they both demo’d it at MIX08 in their respective presentations. Lets re do our WrapPanel to use animating Panel Base and see how cool we can make it.


If we start with the lame wrap panel from earlier we first need to change its base class so the first line should now look like this (you can download the source from the panel factory project on HackingSilverlight.net):


public class WrapPanel : AnimatingPanelBase


Now we have the dispatch timer magic infrastructure. Next we need to add a property and method to our class like this listing that gives us a completed event for animations.

private bool MyFirstTime = true;
void WrapPanel_AnimationCompleted(object sender, RoutedEventArgs e)
{
MyFirstTime = true;
}


Next we need to actually wire this event up in the object constructor. This way the event handler gets called when the first animation is complete. The code we add to a class constructor is:


AnimationCompleted += new RoutedEventHandler(WrapPanel_AnimationCompleted);


Now once complete we are done with ‘additional’ members but we still need to change the ArrangeOverride method. First where we were calling element.arrange we need to replace that code with this block:

if (MyFirstTime)
{
SetElementLocation(element,
new Rect(Left, 1500, Width, Height), false);
}
else
{
SetElementLocation(element, new Rect(Left, Top, Width, Height));
}

In this case if we are starting from the first animation we are animating from a location way off and below the screen. This would almost complete it but we need to another block to deal with the initial run of the arrange. The following listing goes right before the return at the end of the method:

if (MyFirstTime && this.Children.Count > 0)
{
MyFirstTime = false;
this.InvalidateMeasure();
}

On first run we then start at some weird location so we need to make 2 passes to be able to properly lay out elements and then get them to animate to the correct position. In this case on first time where there is more then 0 returned we set the value to false and invalidate measure. This has the effect of allowing us to animate from a starting position.

Now that we have written an animating wrap panel we can use what we have learned to create other kinds of panels that animate. Lets start with the Stack panel. Silverlight already has one but with the animating panel base and our wrap panel we can change a few things and be good to go with some hot animation. In the case of a vertical stacking panel the code change is in the Arrange where we only need one variable:

Double top = 0;

Then when we loop through our children all we need to do is this:

if (_firstArrange)
{
SetElementLocation(e, new Rect(0, 1500,
this.DesiredSize.Width, e.DesiredSize.Height), false);
}
else
{
SetElementLocation(e, new Rect(0, top,
this.DesiredSize.Width, e.DesiredSize.Height));
}
top += e.DesiredSize.Height;

so on first arrange we set everything to some location off screen and then set to the correct location and we set the next top to the current height so things are laid out horizontally. Otherwise the panel is the same as the wrap panel.

you can download the project I have for making this panels at:

http://www.hackingsilverlight.net/samples/PanelFactory.zip

and this is on Beta 1. I'll update this download as I go including new panels and more.

What's Better, Flash or Silverlight?

oh Jason... so not praying at the ms alter just so he can speack the truth... what is up with that?

Here is a good article he did on AJAX RIA Blog on What's Better, Flash or Silverlight?

http://ajax.sys-con.com/read/578783.htm

Creating and Using Panels

If your familiar with WPF (Windows Presentation Foundation) from the programming point of view at all you must know what a panel. A panel in its simplest form is a container like a canvas that manages the layout of the children it contains. In Silverlight, we have a panel base class and a stack panel. The Stack Panel lay’s out its children either horizontally or vertically and can be seen in chapter 3. In WPF one of the more popular ‘Panels’ is a Wrap panel. Currently Silverlight doesn’t have one but using the base class Panel we can create one. This will give us a chance to look at the anatomy of Custom panel and how they work. Lets start by creating WrapPanel class as in this example:

public class LamePanel : Panel { }

From here we need to start by overriding two base members on the Panel class ‘Measure’ and ‘Arrange’. Measure is called so that the size of everything can be calculated before things are laid out and then Arrange is called to actually do the layout. Together the methods should look like this:

protected override Size MeasureOverride(Size availableSize) { }

protected override Size ArrangeOverride(Size FinalSize) { }

These won’t compile yet as we are not returning values so lets work out what each one does to create a Wrap Panel. Lets start with the first method that gets called namely ‘MeasureOverride’. Of the two this is the simplest one. Basically we need to go through each child in the panel and ‘Measure’ it so that we know the size for sure. In the following list we can see is loop through the children calling ‘Measure’ on each child to get it as large as possible with in the size allotted it.


for (int x = 0; x < this.Children.Count; x++)
{
this.Children[x].Measure(
new Size( double.PositiveInfinity, double.PositiveInfinity));
}

return new Size();

We need to return a size so we return a new size at the end. Now once we make sure we call Measure on all the children we can then write our ArrangeOverride method. In Arrange we want to layout all the children of our Panel and in this case we want to lay them out horizontally to the end of the line or width and then wrap the children down to the next line and so forth. The first step is to declare the variables we will use like this listing:

double Top = 0;
double Left = 0;
double Width = 0;
double Height = 0;
double NextTop = 0;

All of these values are used to track the current values used to layout children elements. Next we need to run thorugh each child and do the lay out. Start that process by adding a loop like this example:

foreach (UIElement element in this.Children) { }

From here we need to start be checking each childs desired height and width. We can do that easily like this and set the Width and height values we will need:

Width = element.DesiredSize.Width;
Height = element.DesiredSize.Height;

This gives us a point to start with as we run through each child. Next we need to see if we are still on the same line and if not we need to change a few of the of the base values we are using to move us to the next line using this listing:

if ((Left + Width) > FinalSize.Width)
{
Left = 0;
Top = NextTop;
NextTop = 0;
}


At this point we have our basic values we need to layout the current child so we need to actually do that like this:

element.Arrange(new Rect(Left, Top, Width, Height));

Using the values we calculated we create a new Rectangle and pass this into the element Arrange member. Before being entirely complete with this method we do need to do a little bit more calculation. We need to get the next Left value and the next top value like this listing:

Left = Left + Width;
NextTop = Math.Max(NextTop, Top + Height);

Now we just need to return the Size value that we passed in and our panel is complete. Run it and you can see it wrap and stack the panel children that you add in xaml.

I could show you a few more panels but the key take away is how easy it is to creating layout panels like this.

Wednesday, May 28, 2008

Thursday, April 3, 2008

Actually Using Multi Scale Images in Silverlight - DeepZoom and Mouse Wheel Support with only Silverlight Code...

Using Silver Dragon is pretty straight forward. We start with adding a multiScaleImage to our Xaml and then pointing it at our collection 'bin' file. Generally we would take the output from DeepZoom and then input it into our web project, that we are using to build out our Silverlight application. Then we point the source to the info.bin file. In the case of the collection we built in the last sections it will look something like this:

<MultiScaleImage x:Name="SilverdragonImage" Source="/collection/info.bin" Height="400" Width="400"/>

With just this, when we run our project the MultiScaleImage will animate the zoom of our collection up to the point of being constrained by either the height or width whichever occurs first. Using our collection we created in DeepZoom we then using a default empty solution with only the MultiScaleImage added we will get this figure on the screen.

At this point we can bind events to our MultiScaleImage. The mouse events are typical but we might want to use some of the additional events such as ImageOpenSucceeded, where we can fix up the UI as needed relevant to the image. Once everything is wired up our Xaml.

<MultiScaleImage x:Name="MyFirstMultiScaleImage" Height="400" Width="400"
MouseLeftButtonDown="MyFirstMultiScaleImage_MouseLeftButtonDown" MouseLeftButtonUp="MyFirstMultiScaleImage_MouseLeftButtonUp" MouseMove="MyFirstMultiScaleImage_MouseMove" MouseLeave="MyFirstMultiScaleImage_MouseLeave"
ImageOpenFailed="MyFirstMultiScaleImage_ImageOpenFailed"
ImageOpenSucceeded="MyFirstMultiScaleImage_ImageOpenSucceeded" />

This shows the key events on the MultiScaleImage element we might want to wire up but for zooming in and out we might want to consider using the scroll events, for the mouse wheel off of the window object to give the control rich functionality for users. This will require a bit of hacking in our object so we don't have to use JavaScript in our page. Then we will actually build our class such that it will all be Silverlight code, which by design doesn't support the mouse wheel events. This primarily has to do with the fact, that different browsers expose it differently where we can overcome this in using client side ECMA code, that will be generated in our Silverlight application. Let us start with the click related functionality. For some of the functionality we are going to do, we will need to include another 'using' reference at the top of our application source or C# user control page. The using needs to look like this:

using System.Windows.Browser;

This gives us access to the DOM bridge we will use. To build out all functionality we will use we will need to add some private members and flags for state tacking and references. The initial values we need include the following listing:

public string Source = "SilverDragon/source images/OutputSdi/collection/info.bin";
private bool _IsMouseDown = false;
private bool _IsDragging = false;
private Point _LastImagePoint = new Point(0, 0);
private bool _ErrorState = false;

The first one is used as our Source for MultiScaleImage, the next two are obvious flags for conditions in our application and a point object to show us what the last 'point' was, and the last one is if the class is in an error state and broken. This all need to be members of our user control, and you can tell that is the case by the use of the key word 'private' in front of the declaration. Next we need to make sure the constructor has what it needs to set up the application into the state we will need: The constructor should have the following code listing:

if (Source.IndexOf("http") < 0)
{
string URL = System.Windows.Browser.HtmlPage.Document.DocumentUri.AbsoluteUri;
Source = URL.Substring(0, URL.LastIndexOf('/')) + "/" + Source;
}

MyFirstMultiScaleImage.Source = new Uri(Source);
HtmlPage.RegisterScriptableObject("MySilverlightObject", this);

Here we will make sure the source has a hard URL and if not we will complete it assuming the relative path is relative to our execution location on the server via http. With this we can now look at the actual binding events we use.

void MyFirstMultiScaleImage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (!_ErrorState)
{ MyFirstMultiScaleImage.CaptureMouse();
_IsMouseDown = true; _IsDragging = false;
_LastImagePoint = MyFirstMultiScaleImage.ElementToLogicalPoint(e.GetPosition(MyFirstMultiScaleImage));
}
}

Here we check to see if the application is in its error state and if not we can perform the event. First we capture the mouse in case we are going to do any panning and we test our event flags for mouse down and dragging. Then we get the last point and save it if we are panning and/or zooming in or out. Next let's do our Mouse up with this listing:

void MyFirstMultiScaleImage_MouseLeftButtonUp(object sender, MouseButtonEventArgs e){
if(_IsMouseDown && !_ErrorState)
{
if(!_IsDragging)
{
Point MyPoint = MyFirstMultiScaleImage.ElementToLogicalPoint(e.GetPosition(MyFirstMultiScaleImage));
double ThisFactor = (Keyboard.Modifiers == ModifierKeys.Alt) ? 0.5 : 2;
MyFirstMultiScaleImage.ZoomAboutLogicalPoint(ThisFactor, MyPoint.X, MyPoint.Y);
}
MyFirstMultiScaleImage.ReleaseMouseCapture();
}
_IsMouseDown = false;
}

In this case we can see we checked that the mouse down flag is set and the error state is not true. If those are correct we also check to see if we have been 'dragging,' and if so we grab the current zoom point, calculate a factor based on the alt key, then perform a zoom operation, release the mouse capture and set the mouse down flag to false. This method then deals with either what was the mouse down event or if there was the drag operation or scroll operation. Next we will actually do our mouse move event with this listing.

void MyFirstMultiScaleImage_MouseMove(object sender, MouseEventArgs e)
{
if (_IsMouseDown && !_ErrorState)
{
_IsDragging = true;

Point p = MyFirstMultiScaleImage.ElementToLogicalPoint(e.GetPosition(MyFirstMultiScaleImage));

Point delta = new Point(p.X - _LastImagePoint.X, p.Y - _LastImagePoint.Y);

MyFirstMultiScaleImage.ViewportOrigin = new Point(MyFirstMultiScaleImage.ViewportOrigin.X - delta.X, MyFirstMultiScaleImage.ViewportOrigin.Y - delta.Y);

}
}

Here we first test for the mouse down and error state flags. If they are correct we start our drag operation by setting the value to true. Next we then grab the current point and calculate the delta point, from the last point and then set the viewport origin on our MultScaleImage. Nice and simple right? Now lets add a few methods to help deal with error conditions. First the ImageOpenFailed event that fires if something goes wrong with the source using this listing:

private void MyFirstMultiScaleImage_ImageOpenFailed(object sender, ExceptionRoutedEventArgs e){ _ErrorState = true; }

All it needs to do is set the error state flag if there is a source failure, which will basically set the application into an error state. We could add more code here to do things like switch sources, or something else if we wanted to. Next on the off chance that we are in an error state and the image open succeeds then this method will set the application back into a good state with this listing of the Image Open Succeeded event:

private void MyFirstMultiScaleImage_ImageOpenSucceeded(object sender, RoutedEventArgs e){ _ErrorState = false; }

This sets our application back into a happy state where we can perform deep zoom operations, but next we need to deal with the mouse leave event so we don't leave our MultiScaleImage in a weird state. We do this by using the mouse leave event like this listing:

private void MyFirstMultiScaleImage_MouseLeave(object sender, MouseEventArgs e)
{
_IsDragging = false;
_IsMouseDown = false;
MyFirstMultiScaleImage.ReleaseMouseCapture();
}

Here we reset both; the dragging and mouse down flags and release the mouse capture if it is captured, so we can move on. This basically completes the functionality that Silverlight 2 supports, but we can build mouse wheel support with the following section

HACK - Mouse Wheel Events in SL and with the MultiScaleImage

The 'Mouse Wheel Events' are not really supported. This is in large part due to disparity between how the different browsers support getting this event into a plug in. That however being the case also makes it worth our while to look at the fact that the mouse wheel support inside the context of the scripting engine for browsers is fairly well built out such that we can build a client side solution that feeds into our Silverlight application. However this approach feels like to much of a hack, and we can build out this same hack and make it all in our Silverlight. This still however is a hack, but it really is a lot more pleasant when the Silverlight class can wire all this on its won without us having to build out anything special in our web page (html, asp or whatever). Remember we already added the using statement so we could use the DOM bridge? Now let us start by adding a couple more properties at the top of our class with this listing.

private static string _MOUSEWHEELHANDLER_JS = "function OnMouseWheel() { ($get('Xaml1')).content.MySilverlightObject.MouseWheel(window.event.clientX, window.event.clientY, window.event.wheelDelta); } ";

private static string _MOUSEWHEELEVENT_JS = "window.onmousewheel = document.onmousewheel = OnMouseWheel; if(window.addEventListener) { window.addEventListener('DOMMouseScroll', OnMouseWheel, false); }";

Gasp, I know many of you will note that these two values contain ECMA script. Since Silverlight supports what we need and scripting does, but we don't want to be writing everything in the client, this approach allows all to be built out in our Silverlight code and it makes the class more easily reused. Next we need to add a little private method that does our black magic here with this listing:

private void InsertECMAScript(string JavaScript)
{
HtmlElement Script = HtmlPage.Document.CreateElement("script");
Script.SetAttribute("type", "text/javascript");
Script.SetProperty("text", JavaScript);
HtmlPage.Document.DocumentElement.AppendChild(script);
}

I know this really might give some people heart burn, but it really makes our DeepZoom class more portable. In this case anything we pass into this element will get tacked onto the end of our web page HTML DOM and since it is script up front it gets executed. We use this function in our object constructor like this:

InsertECMAScript(_MOUSEWHEELHANDLER_JS);
InsertECMAScript(_MOUSEWHEELEVENT_JS);

Again, this is really giving some people heart burn, but I think it is cool and much less hassle. One thing to note though is we still didn't add our Mouse Wheel event in our code. Todo this we can add this event handler as in this listing:

[ScriptableMember]
public void MouseWheel(double x, double y, int delta)
{
if (!_ErrorState && !_IsDragging)
{
double ZoomMultiple = (delta < 0) ? 1 / 1.33 : 1.33;

Point p = MyFirstMultiScaleImage.ElementToLogicalPoint(new Point(x, y));

MyFirstMultiScaleImage.ZoomAboutLogicalPoint(ZoomMultiple, p.X, p.Y);
}
}

When we compile it and run it, we now get the click zoom in and out behavior. We can use the alt key when we zoom out on click, and the mouse wheel event is tied into our MultiScaleZoom and it is a reusable class.

Tuesday, April 1, 2008

WCF and Silverligth 2 - Beta 1 and automated builds

One issue I ran into recently was the fact that currently the Silverlight 2 autogenerated client code for WCF services is autogenerated. This is not a big deal typically, but here is where I found some issues... (actually it wasn't me but this guy Sina that found the problem and some one on Mike H's team that explained it) but this is what was found.

We are doing this pretty big silverlight application that is pretty much a shrink wrapped quality solution. Part of the implementation of this is a complete automated build system for QA and part of that was the fact that the production environment is a huge hands off big no touching sort thing.

In this particular application we have a number of WCF services that we are talking to, that are local in the web solution along with the silverlight application. When you run this in Visual Studio it works well. When we deployed it we noticed we had to deploy the solution, re do the references to the deployed WCF service and then deploy again. a bit of a pain but in and automated scenerio using msbuild and the like and you have no idea what the url will be, this is extremely problematic.

We also found a nice service client config file with the url settings for the server etc in the compiled xap but when changed this didn't seem to do anything. Much to our sadness we found out that we might look for this in the next version and the file though created was ignored. The solution that hopefully will go away in Beta 2 is to over-right all our constructors and pass in a value we configure in the web.config... Basically something like this:

ServiceClient MyClient = new ServiceClient( new BasicHttpBinding(), new EndpointAddress( new Uri(SomeConfigValueAsString)));

basically overright which constructor is used and pass in the value that would normally be compiled directly into the dll. A hack I know but it works until we get that beta 2 and we can still use our WCF service.

New Look and Feel

With much sadness I have updated the core template for the hackingsilverlight.net site. Before the site used a nice little bit of code that denied the users w/o silverlight from getting anything. The new template although bazardized from the nice template done in Blend that Ariel sent me is much cooler and doesn't remove all the text content if you don't have silverlight. In fact if you don't pay close attention you might not even notice that it is using a Silverlight header. :)

Wednesday, March 26, 2008

Silverlight Spy

talk about hacking some silverlight :) this is a cool tool

"Silverlight Spy provides detailed XAML inspection of any Silverlight application. Use the built-in browser to navigate to a web page. Silverlight Spy will automatically pick up any Silverlight application embedded in the page and display..."

http://www.silverlightspy.com/silverlightspy/

Tuesday, March 25, 2008

Foundation Blend 2 - Building Applications

I work with this guy Victor that finished his book first. Its more a Blend centric book but promisses to be really good. Of course not to distract anyone from buying my book when it comes out :) but with much ado here it is:

http://windowspresentationfoundation.com/index.html

Thursday, March 20, 2008

Full Screen Silverlight 2

So I"m porting my old silverlight bits to silverlight 2 and I noticed I didn't see much are doing this so I thought I would post this up here for everyone. So in this case I'm making a media player control that I can drop in where ever I need it but I want it to be able to go to full screen. In my class I create a method like this:


private void TopElement_OnFullScreenChanged(object sender, EventArgs e)
{
SizeUI();
}

right now this calls a method that mucks up my UI depending on control size so when it is in full screen it just uses all the realestate. In the class constructor I bind this method to the host like this:


Application.Current.Host.Content.FullScreenChanged += new EventHandler(TopElement_OnFullScreenChanged);
I then create a bit of xaml that points at this method:


private void Canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if( SLHost.Content.IsFullScreen )
{
SLHost.Content.IsFullScreen = false;
}
else
{
SLHost.Content.IsFullScreen = true;
}
}

which that actually is dependent on this being a private member:


private SilverlightHost SLHost = new SilverlightHost();

with that nice a simple bit of code I have full screen mode :)

Thursday, March 13, 2008

Using Expression DeepZoom

The key tool for building out MultiScaleImages we will use in Silverlight is Expression DeepZoom. DeepZoom is a Simple tool like Encoder for example that allows you to import images and produce the multi-layer image collections and tile structure used by DeepZoom (MultiScaleImages) in Silverlight to produce the coolness we are looking for.


DeepZoom (talk about double entendre) then creates a DeepZoom Project lets you import all the high resolution images you want to use. Then you can compose your collection of images and then it will export and build all of your multilayer image collections, tiles and other bits as configured. With that then we can embed these into Silverlight work with multilayered images.
We learn how to use the application by opening Expression DeepZoom and getting familiar with the user interface.


Currently the interface is pretty simple. We have our splash screen that pops up. That shows existing projects or lets you open new ones etc. We also can see the tabs which are basically the 3 steps to building a Multi layered image collection and getting it ready for Silverlight. From the top file menu we can open the project dialog.


Once we give our project a name and select the type (Seadragon Project) we then can start adding images to our multi-layered image collection. On the import tab in the UI we can see we have a view area and then a scrolllist of our images. At first this will be blank and at the bottom we have a button called 'Add Image.' If you click the 'Add Image' button you can use the standard windows API file dialog to find a cool high resolution image that you want to multi layer. If you add several you will see them on the design surface.


Now that we have added some images we can start arranging them in our collection. Start by click on the tab '2. Compose' at the top of the interface. Then you can drag the images from the right on to our design surface.


Let us take a look at the interface. At the top of the UI we can see a tool bar at the top and there are 5 tools which by default will have the first one selected. The first three icons represent the cursor state on the compose view of the application. The default is for dragging our icons onto the surface. Selecting second icon you can drag the design surface.


You can see how the map in the lower left of the composition surface has moved showing what the pan functionality looks like and this map shows you where on the surface that you are. The third icon on the compose tool bar is for zooming. This allows you to drill into any given location on the composition surface.


Looking closely we can see the drop down menus for the last two icons on the composition tool bar. You can see the second icon from the right is alignment items (i.e. left, right, top, bottom etc). if you select one then all your images get laid out in the collection accordingly. The menu for the last button that distributes images horizontally or vertically.


Once we get all our images on our composition surface we are ready to export our collection. There are a number of settings but for DeepZoom in Silverlight we are good with just having a location and exporting. We do this by clicking the export button.


DeepZoom then builds our Silver Dragon (SDI) file and builds out all over tiled images. If we are just going to use it for Silverlight and are using one image we can just grab its corresponding structure including the .bin, xml and the tile jpg's. Now we are ready to actually do Seadragon, er I mean SilverDragon, er I mean DeepZoom(MultiScaleImages).

Tuesday, March 11, 2008

ItemsControl, ListBox and DataGrid's, oh my

The ItemControl's coolest use is to layout 'items' via an item template using data binding to a collection. As a functional control this really requires more than just some Xaml and in fact we will walk through the process in order so we never have Visual Studio throwing some errors. In your page behind you will need to make sure you include these libraries as show here:

using System.ComponentModel;
using System.Collections.ObjectModel;

This gives us access to ObservableCollection and INotifyPropertyChanged so we can build out our data. We will create a method that create our collection but first we need a base classes for our data. To start with we need to create the Data class first like this:

public class Data : INotifyPropertyChanged
{
private object _value;
public event PropertyChangedEventHandler PropertyChanged;

public Data(object val) { _value = val; }

private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}

This inherits from INotifPropertyChanged and we create our NotifyPropertyChanged method along with a constructor so we can pass our value in when we create instances of the class. Since we have a private value we need to expose it publicly so we can then bind our templates to it as used in the items control. So then we add the following code to the above class:

public object Value
{
get { return _value; }
set
{
if (value != _value)
{
_value = value;
NotifyPropertyChanged("Value");
}
}
}

This 'Value' public property is what we will actually bind to. Then we can create our DataCollection that is an ObservableCollection of our Data Class like this:

public class DataCollection : ObservableCollection<Data> { }

Now we have an ObservableCollection that we can bind to. Next we need to create a method that creates or gets the data. Here we will hard code the data into this simple example:

private object GetData()
{
DataCollection MyCollection = new DataCollection();
MyCollection.Add(new Data("One"));
MyCollection.Add(new Data("Two"));
return MyCollection;
}

Let us now look at our Xaml, now that we have our collection and something to create it or fill it with data we need an items control and template to do something with. First we build our template for each item that will be listed in the items control.

<UserControl.Resources> <DataTemplate x:Name="MyDataTemplate" > <TextBlock Text="{Binding Value}" ></TextBlock> </DataTemplate> </UserControl.Resources>

This will bind to the public value of 'Value' as created in our data class earlier. Next we need to actually create the items control. An Items control can be as simple as this:

<ItemsControl x:Name="itemsControl" ItemsSource="{Binding}" ItemTemplate="{StaticResource MyDataTemplate}" >
</ItemsControl>

In this case we set our ItemSource to be Binding and then we use a static resource namely our template. Back to our code we now need to point the items control to the method that creates our collection using code like this:

this.itemsControl.DataContext = GetData();

This can be in our page's or user controls constructor and sets the data context to be the collection of objects as an observable collection that we are building and returning. When we run this we will get a list of items as created in the GetData method much like a stack panel would lay out its children where in this case the default is vertically.

Not terribly impressive but under the covers very cool. What is most cool about it is the key functionality this provides. This can be used for everything from dynamically build menus and other dynamic lists of different kinds and more. To move beyond that we can also use the new control Listbox.

Using the Listbox control

The Listbox control is much like the ItemsControl but we are adding functionality including scrolling and selection rollover functionality. We can style it and using databinding and the like just the same. So using the code from the last section we can change out our Xaml and be ready. To start with add additional elements in the collection in our source this way we have 20 or so elements so we can see the scroll functionality. Then we can remove the ItemsControl and add a Listbox like this example:

<ListBox x:Name="itemsControl" Grid.Row="1"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource MyDataTemplate}" />

So by adding all the extra items to our collection we can really see the big difference between ItemsControl and Listbox control.

With the Listbox control it is easier to implement functionality like select or drop down functionality that users see in other technologies. Now to take this even one step further lets look at DataGrid.

Using the Datagrid Control

The Datagrid is used much like the list and items controls but the datagrid is targeted towards result set functionality. In this case we need to make sure we specify the name space in the xaml. At the top if you use Visual Studio and start to create a name space it will give you a list and you want to select the 'System.Windows.Control.Data'. You can give your 'namespace' any name you want but since it's a Datagrid we are talking about I'm partial to 'Data' as a matter of course. So lets assume the same code base as the Listbox we did earlier, then rip out our 'ListBox' and then add this bit of Xaml

<Data:DataGrid x:Name="itemsControl" AutoGenerateColumns="True" ItemsSource="{Binding}" />

When we run this we get a nice data grid like the ListBox but we get column names. We can of course re-template this to look pretty much any way we like but default will look pretty much like any data grid control you might see in winforms.

As you can see its pretty much the same as the ListControl and ItemsControl but Columns are added and we have set it to auto-generate the columns.

Wednesday, March 5, 2008

Download links from MIX 08 - Silverlight

here is a link to a list Tim pushed to his blog with all the download links:

http://blogs.msdn.com/tims/archive/2008/03/05/download-links-for-mix08-announcements.aspx

Silverlight MIX Announcement(s)

In the keynote today Scott G annouced SL 2. is publicly available. very cool. my favorite part whas how much they showed our Entertainment Tonight work in Silverlight. among my favorite features annouced include (I will skip all the new bits Scott put out on his blog last week):

* support for Silverlight on MAC, Windows, Linux and Mobile devices
* improved preformance especially dynamic adaptive streaming and bit rate throttling, including IIS features to support to provide bit rate throttling.
* Silverlight Add templates in visual studio
* Burning Silverlight right into video using ecoder 2
* Multi-language including Silverlight in Python
* Rich WPF UI framework (layout, databinding, skinning and styling system)
* Robust networking (post, SOAP, WCF, sockets etc.)
* LINQ and Databinding
* Local Store and cache between browser sessions
* Controls include: data grids, list box, sliders, radios, buttons calender and date picker controls, checkboxs etc.
* all controls are being shipped with open source license.
* test framework for silveright.
* control templating stucture including the abilty to change animations, and restructure the visual tree
* full intellisense and design experience in VS
* DeepZoom.... formerly Silverdragon formerly SeaDragon taking smut to the next level allowing arbitrary zooming to any resolution smoothly.
* Silverlight Sharepoint bits to make it easier to put silverlight web parts in sharepoint

SeaDragon (DeepZoom) really is cool with the 2billion pixel size images... :)

IE 8.0 first impressions

So one of the first things we are seeing in the MIX keynote is IE 8.0 which seems to be more about standards and helping developers do better work. So far we got some CSS 2.1 support, HTML 5, in proved perf especially with script, more itegrated debugging tools and visual related tools directly in IE if a user wants. there are better tools for users like being able to select text and IE will provide services tools based on the text. That sounds problematic but seeing it work is really cool. And web slices are cool.

beta 1 is available at:

http://www.microsoft.com/ie/ie8/

MIX 08 - Silverlight - Wish you were here...

Ah MIX... its finally here. Hmm... we will see what kind of coolness comes out of mix. The conference starts wed and since it is sooo late that I got back to my room in the Venetian that it actually starts later today. Anyway I digress. Even though the conference started I have learned alot. I spoke with Laurence (another author of the MS press book Silverlight 1.0) about publishers and our up coming books and the like. Plus there was the Silverligth Insiders 'meeting' such that it was at the V Bar. We can to meet some of the guys we didn't know and talk with some of the guys we did. Adam has blue hair and we will see how the rest goes but we still can't talk about too much. Also Nokia annouced that their phones will support Silveright so i think it is safe to extrapolate that MS is going to get it on windows CE. Oh plus the plane ride up... well I guess I have to save the good stuff for after the key note.

Monday, March 3, 2008

No Soap for you! - The No Silverlight Experience

So I'm collecting hacks for my upcoming book, and I must say, here is a simple one, but one of my favorites... LOL!

On my HackingSilverlight.net (the domain not the feed site), I did not have time to worry about the non-silverlight user and in fact chose to be a bit over-the-top towards them. Personally I find it funny, but I know many people think its just plain mean... but really what is someone doing at a Silverlight site if they don't have silverlight? So to save me from work, here is my on-load function...

function OnLoad()
{
Resize();
try
{
if( !Silverlight.isInstalled("1.0") )
{
var parentElement = document.getElementById("BlogContent");
parentElement.innerHTML = "";
}
}
catch(Exception)
{
alert('NO SOUP FOR YOU!...');
}
}


Note the 'innerHTML' which would normally contain the entire HTML block that makes up all the visible content on the page except the install badge... again I found this extremely funny, but alas, with the book coming, I will probably make it play nice.