Try it here.
See a picture below:
I ran into one odd issue when using Silverlight 2.0 Beta 2….
void Page_Loaded(object sender, RoutedEventArgs e) { // if you don't invoke this asynchronously, you can't add at load time // (seems to be a silverlight 2.0 issue) Dispatcher.BeginInvoke(delegate() { consoleCanvas.AnimateNewChild( string.Format("Welcome!\nThe time right now is {0}.", DateTime.Now.ToLocalTime())); consoleCanvas.AnimateNewChild("\n\nThanks for stopping by WiredPrairie.us. " + "This code may be used for only for good, not evil."); }); }
The code above for example — if the ConsoleCanvas control (the simple base control for the console output-like functionality) performs any UpdateLayout calls within the context of the Load event, the entire Silverlight control fails to load, silently. The only work-around I could discover was to delay what I wanted to occur by using the asynchronous invoke method on the Dispatcher object.
The easiest way to force a UIElement to measure itself is to use a little trick:
_holder.Width = this.ActualWidth; child.Width = this.ActualWidth; _holder.Children.Add(child); _holder.UpdateLayout(); child.Width = child.DesiredSize.Width; child.Height = child.DesiredSize.Height;
The console control maintains a visible (yet opacity is set to 0.0) StackPanel. Each time a new line of output is added via the AnimateNewChild method, it’s placed in the StackPanel. The StackPanel (_holder) is resized to fit the current width of the entire ConsoleCavnas control. Next, the UpdateLayout method of the StackPanel is called — which forces an immediate measure of all of the children (and thus forces any children of the TextPanel to potentially re-layout). The width and height are grabbed and permanently stored as the new size for the child.
Instead of using Storyboards and various animations, I found it more convenient to simply use a DispatchTimer and do the animations manually.
List<FrameworkElement> remove = new List<FrameworkElement>();
for(int childIndex = 0; childIndex < this.Children.Count; childIndex++) { FrameworkElement child = this.Children[childIndex] as FrameworkElement; if (!child.Equals(_holder)) { child.Arrange(new Rect(0, Canvas.GetTop(child), 0, 0)); double top = Canvas.GetTop(child); top -= 2.0; Canvas.SetTop(child, top); if (top + child.Height < 0.0) { remove.Add(child); } } } // remove them all remove.ForEach(fe => this.Children.Remove(fe as UIElement));
If an element is no longer visible on the screen, it is removed using a Lambda expression and the ForEach method on the List object instance named remove (after the repositioning loop has completed).
Download source, etc. here.


Be The First To Comment
Related Post
Please Leave Your Comments Below