Click here to Skip to main content
15,886,873 members
Articles / Programming Languages / C#

A Simple Solution to Some Problems with Asynchrony in Silverlight

Rate me:
Please Sign up or sign in to vote.
4.69/5 (8 votes)
9 Mar 2010CPOL15 min read 24.9K   128   25  
A small, extensible suite of classes that elegantly solve some common problems involving asynchrony and event handling that tend to occur when Silverlight and WCF are used together.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;

namespace TaskManagerDemo.Controls
{
    [TemplatePart(Name = PopupWindow.titleBarElement, Type = typeof(FrameworkElement))]
    [TemplatePart(Name = PopupWindow.statusBarElement, Type = typeof(FrameworkElement))]
    [TemplatePart(Name = PopupWindow.windowBorderElement, Type = typeof(Border))]
    [TemplatePart(Name = PopupWindow.buttonsElement, Type = typeof(Panel))]
    [TemplatePart(Name = PopupWindow.contentContainerElement, Type = typeof(Border))]
    [TemplatePart(Name = PopupWindow.closeButtonElement, Type = typeof(Button))]
    [TemplatePart(Name = PopupWindow.resizeElement, Type = typeof(FrameworkElement))]
    [TemplatePart(Name = PopupWindow.modalMaskElement, Type = typeof(Rectangle))]
    [TemplatePart(Name = PopupWindow.errorBackgroundElement, Type = typeof(Brush))]
    [TemplatePart(Name = PopupWindow.actionRequiredBackgroundElement, Type = typeof(Brush))]
    [TemplatePart(Name = PopupWindow.titleBackgroundElement, Type = typeof(Brush))]
    [TemplatePart(Name = PopupWindow.titleTextElement, Type = typeof(TextBlock))]

    public class PopupWindow : DragDropControl
    {
        private const string titleBarElement = "TitleBar";
        private const string statusBarElement = "StatusBar";
        private const string buttonsElement = "Buttons";
        private const string contentContainerElement = "ContentContainer";
        private const string windowBorderElement = "WindowBorder";
        private const string closeButtonElement = "CloseButton";
        private const string resizeElement = "ResizeImage";
        private const string modalMaskElement = "ModalMask";
        private const string errorBackgroundElement = "ErrorBackground";
        private const string titleTextElement = "TitleText";
        private const string actionRequiredBackgroundElement = "ActionRequiredBackground";
        private const string titleBackgroundElement = "TitleBackground";
        private const string cmErrorBackgroundElement = "CMErrorBackground";

        protected Button CloseButton;
        protected Border ContentContainer;
        protected Border WindowBorder;
        protected FrameworkElement ResizeImage;
        protected FrameworkElement StatusBar;
        protected Rectangle ModalMask;
        protected Border TitleBar;
        protected Brush ErrorBackground;
        protected TextBlock TitleText;
        protected Brush ActionRequiredBackground;
        protected Brush TitleBackgroundColor;
        protected Brush CMErrorBackgroundColor;

        #region IsModal

        public EventHandler<EventArgs> Closed;

        /// <summary>
        /// Identifies the IsModal dependency property.
        /// </summary>
        public static readonly DependencyProperty IsModalProperty = DependencyProperty.Register("IsModal", typeof(bool), typeof(PopupWindow), null);

        /// <summary>
        /// Gets or sets the IsModal possible Value of the bool object.
        /// </summary>
        public bool IsModal
        {
            get { return (bool)GetValue(IsModalProperty); }
            set { SetValue(IsModalProperty, value); }
        }

        #endregion IsModal
        #region IsCloseButtonDisabled

        /// <summary>
        /// Identifies the IsModal dependency property.
        /// </summary>
        public static readonly DependencyProperty IsCloseButtonDisabledProperty = DependencyProperty.Register("IsCloseButtonDisabled", typeof(bool), typeof(PopupWindow), null);

        /// <summary>
        /// Gets or sets the IsModal possible Value of the bool object.
        /// </summary>
        public bool IsCloseButtonDisabled
        {
            get { return (bool)GetValue(IsCloseButtonDisabledProperty); }
            set { SetValue(IsCloseButtonDisabledProperty, value); }
        }

        #endregion IsCloseButtonDisabled
        #region IsCloseButtonVisibleProperty

        /// <summary>
        /// Identifies the IsModal dependency property.
        /// </summary>
        public static readonly DependencyProperty IsCloseButtonVisibleProperty = DependencyProperty.Register("IsCloseButtonVisible", typeof(bool), typeof(PopupWindow), null);

        /// <summary>
        /// Gets or sets the IsModal possible Value of the bool object.
        /// </summary>
        public bool IsCloseButtonVisible
        {
            get { return (bool)GetValue(IsCloseButtonVisibleProperty); }
            set { SetValue(IsCloseButtonVisibleProperty, value); }
        }

        #endregion IsCloseButtonVisibleProperty

        public void ShowCloseButton()
        {
            if (CloseButton != null)
            {
                if (!IsCloseButtonVisible)
                    CloseButton.Visibility = Visibility.Collapsed;
                else
                    CloseButton.Visibility = Visibility.Visible;
            }
        }

        #region ShowStatus

        /// <summary>
        /// Identifies the ShowStatus dependency property.
        /// </summary>
        public static readonly DependencyProperty ShowStatusProperty = DependencyProperty.Register("ShowStatus", typeof(bool), typeof(PopupWindow), null);

        /// <summary>
        /// Gets or sets the ShowStatus possible Value of the bool object.
        /// </summary>
        public bool ShowStatus
        {
            get { return (bool)GetValue(ShowStatusProperty); }
            set { SetValue(ShowStatusProperty, value); }
        }

        #endregion ShowStatus
        #region Title

        /// <summary>
        /// Identifies the Title dependency property.
        /// </summary>
        public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(PopupWindow), null);

        /// <summary>
        /// Gets or sets the Title possible Value of the string object.
        /// </summary>
        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }

        #endregion Title
        #region TitleBackground

        /// <summary>
        /// Identifies the TitleBackground dependency property.
        /// </summary>
        public static readonly DependencyProperty TitleBackgroundProperty = DependencyProperty.Register("TitleBackground", typeof(Brush), typeof(PopupWindow), null);

        /// <summary>
        /// Gets or sets the TitleBackground possible Value of the Brush object.
        /// </summary>
        public Brush TitleBackground
        {
            get { return (Brush)GetValue(TitleBackgroundProperty); }
            set { SetValue(TitleBackgroundProperty, value); }
        }

        #endregion TitleBackground
        #region Status

        /// <summary>
        /// Identifies the Status dependency property.
        /// </summary>
        public static readonly DependencyProperty StatusProperty = DependencyProperty.Register("Status", typeof(string), typeof(PopupWindow), new PropertyMetadata(OnStatusPropertyChanged));

        /// <summary>
        /// Gets or sets the Status possible Value of the string object.
        /// </summary>
        public string Status
        {
            get { return (string)GetValue(StatusProperty); }
            set { SetValue(StatusProperty, value); }
        }

        /// <summary>
        /// StatusProperty property changed handler.
        /// </summary>
        /// < param name="d">PopupWindow that changed its Status.</param>
        /// < param name="e">DependencyPropertyChangedEventArgs.</param>
        private static void OnStatusPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            PopupWindow _PopupWindow = d as PopupWindow;
            if (_PopupWindow != null)
            {
            }
        }

        #endregion Status

        public PopupWindow()
        {
            this.DefaultStyleKey = typeof(PopupWindow);
            this.CanResize = true;
            this.ShowStatus = true;
        }

        public void Close()
        {
            if (this.ModalMask != null)
            {
                this.ModalMask.Visibility = Visibility.Collapsed;
            }
            this.Visibility = Visibility.Collapsed;
            if (Closed != null)
            {
                Closed(this, null);
            }
        }

        public void Show()
        {
            if (this.ModalMask != null)
            {
                this.ModalMask.Visibility = Visibility.Visible;
            }
            this.Visibility = Visibility.Visible;
        }

        private void ShowMask()
        {
            if (this.IsModal && this.ModalMask != null)
            {
                Panel p = this.Parent as Panel;
                if (p != null)
                {
                    Grid g = p as Grid;
                    if (g != null)
                    {
                        if (g.ColumnDefinitions.Count > 1)
                            ModalMask.SetValue(Grid.ColumnSpanProperty, g.ColumnDefinitions.Count);
                        if (g.RowDefinitions.Count > 1)
                            ModalMask.SetValue(Grid.RowSpanProperty, g.RowDefinitions.Count);
                    }
                    this.Root.Children.Remove(ModalMask);
                    p.Children.Add(ModalMask);
                    ModalMask.SetValue(Canvas.ZIndexProperty, DragDropControl.MaxZIndex);
                    DragDropControl.MaxZIndex++;
                    this.SetValue(Canvas.ZIndexProperty, DragDropControl.MaxZIndex);
                    DragDropControl.MaxZIndex++;
                }
            }
        }

        #region IsErrorDialog

        /// <summary>
        /// Identifies the IsModal dependency property.
        /// </summary>
        public static readonly DependencyProperty IsErrorDialogProperty = DependencyProperty.Register("IsErrorDialog", typeof(bool), typeof(PopupWindow), null);

        /// <summary>
        /// Gets or sets the IsModal possible Value of the bool object.
        /// </summary>
        public bool IsErrorDialog
        {
            get { return (bool)GetValue(IsErrorDialogProperty); }
            set { SetValue(IsErrorDialogProperty, value); }
        }

        #endregion IsErrorDialog
        #region IsCMErrorDialog

        /// <summary>
        /// Identifies the IsModal dependency property.
        /// </summary>
        public static readonly DependencyProperty IsCMErrorDialogProperty = DependencyProperty.Register("IsCMErrorDialog", typeof(bool), typeof(PopupWindow), null);

        /// <summary>
        /// Gets or sets the IsModal possible Value of the bool object.
        /// </summary>
        public bool IsCMErrorDialog
        {
            get { return (bool)GetValue(IsCMErrorDialogProperty); }
            set { SetValue(IsCMErrorDialogProperty, value); }
        }

        #endregion IsCMErrorDialog
        #region IsActionRequiredDialog

        /// <summary>
        /// Identifies the IsModal dependency property.
        /// </summary>
        public static readonly DependencyProperty IsActionRequiredDialogProperty = DependencyProperty.Register("IsActionRequiredDialog", typeof(bool), typeof(PopupWindow), null);

        /// <summary>
        /// Gets or sets the IsActionRequiredDialog possible Value of the bool object.
        /// </summary>
        public bool IsActionRequiredDialog
        {
            get { return (bool)GetValue(IsActionRequiredDialogProperty); }
            set { SetValue(IsActionRequiredDialogProperty, value); }
        }

        #endregion IsActionRequiredDialogDialog
        #region IsTitleBarHidden

        /// <summary>
        /// Identifies the IsModal dependency property.
        /// </summary>
        public static readonly DependencyProperty IsTitleBarHiddenProperty = DependencyProperty.Register("IsTitleBarHidden", typeof(bool), typeof(PopupWindow), null);

        /// <summary>
        /// Gets or sets the IsModal possible Value of the bool object.
        /// </summary>
        public bool IsTitleBarHidden
        {
            get { return (bool)GetValue(IsTitleBarHiddenProperty); }
            set { SetValue(IsTitleBarHiddenProperty, value); }
        }

        public void ShowActionRequiredTitleBar()
        {
            if (IsActionRequiredDialog)
            {
                if (TitleText != null)
                {
                    TitleText.HorizontalAlignment = HorizontalAlignment.Center;
                    TitleText.FontSize = 30;
                }
                if (ActionRequiredBackground != null)
                    TitleBar.Background = ActionRequiredBackground;
            }
        }

        public void ShowHideTitleBar()
        {
            if (IsTitleBarHidden && !IsActionRequiredDialog)
            {
                if (WindowBorder != null)
                {
                    if (IsErrorDialog)
                    {
                        if (IsCMErrorDialog)
                        {
                            WindowBorder.CornerRadius = new CornerRadius(0);
                            WindowBorder.Background = CMErrorBackgroundColor;
                        }
                        else
                        {
                            WindowBorder.CornerRadius = new CornerRadius(10, 10, 10, 10);
                            WindowBorder.Background = ErrorBackground;
                        }
                    }

                    else
                    {
                        WindowBorder.CornerRadius = new CornerRadius(5, 5, 5, 5);
                        WindowBorder.BorderBrush = new SolidColorBrush(Colors.LightGray);
                        WindowBorder.Background = new SolidColorBrush(Colors.White);
                    }
                }
                if (TitleBackground != null)
                {
                    TitleBackground = new SolidColorBrush(Colors.Transparent);
                }
                if (TitleBar != null)
                {
                    TitleBar.Background = new SolidColorBrush(Colors.Transparent);
                }
                if (CloseButton != null)
                    CloseButton.Visibility = Visibility.Collapsed;
                if (TitleText != null)
                {
                    if (IsErrorDialog || IsActionRequiredDialog)
                    {
                        TitleText.HorizontalAlignment = HorizontalAlignment.Center;
                        if (!IsCMErrorDialog)
                        {
                            TitleText.FontSize = 30;
                        }
                        else
                            TitleText.FontSize = 15;
                    }
                    else
                    {
                        TitleText.FontSize = 10;
                    }
                }
                if (ContentContainer != null)
                {
                    ContentContainer.Background = new SolidColorBrush(Colors.Transparent);
                }
            }
            else if (IsActionRequiredDialog)
            {
                ShowActionRequiredTitleBar();
            }
        }

        #endregion IsTitleHidden
        #region Overrides

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            WindowBorder = GetTemplateChild(windowBorderElement) as Border;

            CloseButton = this.GetTemplateChild(closeButtonElement) as Button;
            if (CloseButton != null)
            {
                if (!this.IsCloseButtonDisabled)
                    CloseButton.Click += new RoutedEventHandler(CloseButton_Click);
                ShowCloseButton();
            }

            ContentContainer = this.GetTemplateChild(contentContainerElement) as Border;
            if (ContentContainer != null)
                ContentContainer.MouseLeftButtonDown += new MouseButtonEventHandler(ContentContainer_MouseLeftButtonDown);
            TitleBar = GetTemplateChild(titleBarElement) as Border;
            ErrorBackground = GetTemplateChild(errorBackgroundElement) as Brush;
            CMErrorBackgroundColor = GetTemplateChild(cmErrorBackgroundElement) as Brush;
            ActionRequiredBackground = GetTemplateChild(actionRequiredBackgroundElement) as Brush;
            TitleText = GetTemplateChild(titleTextElement) as TextBlock;
            if (TitleText != null)
                TitleText.FontSize = 12;
            TitleBackgroundColor = GetTemplateChild(titleBackgroundElement) as Brush;
            if (TitleBar != null)
            {
                TitleBar.Background = TitleBackgroundColor;
                if (IsActionRequiredDialog)
                    ShowActionRequiredTitleBar();
                else
                    ShowHideTitleBar();
            }

            ResizeImage = GetTemplateChild(resizeElement) as FrameworkElement;
            if (ResizeImage != null && !this.CanResize)
                ResizeImage.Visibility = Visibility.Collapsed;
            StatusBar = GetTemplateChild(statusBarElement) as FrameworkElement;
            if (StatusBar != null && !this.ShowStatus)
            {
                RowDefinition r = GetTemplateChild("StatusRow") as RowDefinition;
                if (r != null)
                    r.MaxHeight = 0;
                StatusBar.Visibility = Visibility.Collapsed;
            }
            if (this.IsModal)
            {
                ModalMask = GetTemplateChild(modalMaskElement) as Rectangle;
                this.Dispatcher.BeginInvoke(ShowMask);
            }
        }

        private void CloseButton_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
            if (Closed != null)
                Closed(this, null);
        }

        private void ContentContainer_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;
        }

        private void handlerCompletedRemove(object sender, EventArgs e)
        {
        }

        #endregion Overrides
    }

    public static class Position
    {
        public enum Corner
        {
            LeftTop,
            LeftBottom,
            RightTop,
            RightBottom
        }

        public static Point GetAbsolutePosition(FrameworkElement e)
        {
            return GetAbsolutePosition(e, Corner.LeftTop);
        }

        public static Point GetAbsolutePosition(FrameworkElement e, Corner p)
        {
            return GetRelativePosition(e, Application.Current.RootVisual as FrameworkElement, p);
        }

        public static Point GetRelativePosition(FrameworkElement e, FrameworkElement relativeTo)
        {
            return GetRelativePosition(e, relativeTo, Corner.LeftTop);
        }

        public static Point GetRelativePosition(FrameworkElement e, FrameworkElement relativeTo, Corner corner)
        {
            GeneralTransform gt = e.TransformToVisual(relativeTo);

            Point result = new Point();
            if (corner == Corner.LeftTop)
                result = gt.Transform(new Point(0, 0));
            if (corner == Corner.LeftBottom)
                result = gt.Transform(new Point(0, e.ActualHeight));
            if (corner == Corner.RightTop)
                result = gt.Transform(new Point(e.ActualWidth, 0));
            if (corner == Corner.RightBottom)
                result = gt.Transform(new Point(e.ActualWidth, e.ActualHeight));
            return result;
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Concur
United States United States
George Henry has worked as a software developer for more than 20 years. He is currently employed by Concur in Bellevue, Washington, USA.

Comments and Discussions