These How-To tips are taken from The Tutor.com Classroom: Architecture and techniques using Silverlight, WPF, and the Microsoft .NET Framework.To actually share the code, use compile-time code sharing by choosing “Add As Link” when adding project files, rather than using our source code management’s “Share”. Using the “Add As Link” technique ensures that as changes are made to shared code, successfully building the solution guarantees that the changes are valid across all three applications. Source code management “Share” requires developers to check in their changes, do a “Get Latest Version” on the shared files, rebuild the solution, make any necessary changes, repeat, etc. In the meantime, the build is potentially broken.
You can check out the Silverlight Tutor.com Classroom in "practice" mode, although the real experience is with a live tutor on the other side!
Monday, November 3, 2008
Tutor.com Classroom How-To #1: sharing code between Silverliht and WPF applications
The Tutor.com Classroom: How-To tips from the field
These How-To tips are taken from The Tutor.com Classroom: Architecture and techniques using Silverlight, WPF, and the Microsoft .NET Framework.Tutor.com’s online learning system, the Tutor.com Classroom, utilizes many of the advanced capabilities of the Microsoft .NET 3.5 platform, including TCP/IP sockets and WPF, in addition to making full use of the Silverlight browser plug-in. The next set of blog postings show solutions to some of the more interesting problems and how the potential of .NET was employed.
You can check out the Silverlight Tutor.com Classroom in "practice" mode, although the real experience is with a live tutor on the other side!
- Share code between Silverlight and WPF applications
- Enforce an MVC-style architecture
- Connect to a TCP/IP Listener
- Specify “End-Of-Message” to a TCP/IP Listener
- Provide automatic reader-to-writer lock upgrade
- Create a horizontal WrapPanel that is transform-aware and exposes row and column counts
- Screen-scrape an application via Win32 PrintWindow() API
- Trap and process mouse movement in an InkPresenter
- Create a Path object from a Stroke
- Manually install and detect for the Silverlight plug-in
- Build a Silverlight ToolbarButton user control
Friday, October 17, 2008
WPF gotcha: MessageBox.Show() inside Dispatcher.Invoke
in WPF, if you’re calling MessageBox.Show() inside a Dispatcher.Invoke call (when you’re moving back to the GUI thread from a worker thread), make sure you pass a Window object for the optional first parameter when calling MessageBox.Show (e.g. MessageBox.Show(this, "Message Here", "Title Here");). if you don’t, the message box can show up non-modal alongside your app, which is almost never your intent—
Thursday, October 16, 2008
use a specialized Xml writer when creating xml strings
avoid creating Xml streams by string manipulation (e.g. string s = "<Name First='" + firstName + "' Last='" + lastName + "'/>), since you get no reserved character escaping and will throw an error when certain input characters are processed.
in .NET 3.5, there are two good choices: XDocument (in System.Xml.LINQ) and XmlWriter (in System.Xml). XDocument is particularly powerful, since both it and XElement have param of objects constructors, which means you can specify all elements and each element’s attributes in one statement. it ends up looking very declarative:
XDocument xDoc = new XDocument(
new XElement("Name",
new XAttribute("First", firstName),
new XAttribute("Last", lastName)
));
string encodedXml = xDoc.ToString();
you can use XmlWriter to write directly to a Stream or to a StringBuilder:
StringBuilder sb = new StringBuilder();
using (XmlWriter writer = XmlWriter.Create(sb, new XmlWriterSettings() { OmitXmlDeclaration = true } ))
{
writer.WriteStartElement("Name");
writer.WriteAttributeString("First", firstName);
writer.WriteAttributeString("Id", lastName);
writer.WriteEndElement();
}
string encodedXml = sb.ToString();
Tuesday, September 30, 2008
make sure you manually stop storyboards on hidden objects
storyboards continue to run even if the object you’re animating is invisible, so you’re generally burning CPU cycles for nothing. in silverlight, you can stop any storyboard just by calling Stop:
myStoryboard.Begin();
myStoryboard.Stop();
in WPF, you need to specifically let the runtime know that you want Stop functionality when you call Begin via the isControllable paramater:
myStoryboard.Begin(this, true);
myStoryboard.Stop();
Saturday, September 13, 2008
properties vs. functions
although there’s little difference after compilation, treat properties and functions very different from a logical perspective. properties should almost always be deterministic, i.e. calling the same property twice should return the same value (so object.Property == object.Property must be true). a property can have a lazy get constructor, so it actually does some work the first time it is called, but it must remember the result of that work and return it on subsequent calls. so in general a property returns something stateful or something static.
in all other cases, use a function, and give it a meaningful name based on what it’s doing (i.e. GetRandomNumber(), CreateUser(), etc.).
Thursday, August 7, 2008
Action<> and Func<> delegates
these new generic delegates were added in .NET 3.5 for LINQ, but they’re also very useful in your own classes. Action<> allows you to specify types for up to 4 parameters and returns void, and Func<> does the same except you can also specify a return type. if you look at the LINQ extension methods, you’ll see these delegates extensively.
so for example, if you needed a delegate that returned void and took no parameters, you’d have to write something like:
public delegate void VoidDelegate();
public event VoidDelegate MyEvent;
so what you end up with is repetitive declarations of such a VoidDelegate delegate in lots of classes. now, you can just use the Action<> delegate to do this (Action<> works in any case where you return void and take up to 4 parameters):
public event Action MyEvent;
same goes for Func<>. before, you’d have to create a delegate for each specific set of input variable and return types:
public delegate string TakeTwoStringsAndReturnStringDelegate(string String1, string String2);
and then call it like:
return (String)Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
(TakeTwoStringsAndReturnStringDelegate)delegate
{
return TakeTwoStringsAndReturnString("1", "2");
}
);
return (String)Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
(Func<String, String, String>)delegate
{
return TakeTwoStringsAndReturnString("1", "2");
}
);
there are probably still times when you’ll want to create your own delegate, but these two generics are very useful for filling in the gaps—
