Skip to main content

Microsoft® Surface® Live Stream Code Sample

ive Stream enables businesses to engage their customers face-to-face using the most recent and relevant Twitter™, Flickr®, and RSS newsfeeds.

C# (5.9 MB)
 
 
 
 
 
4.3 Star
(4)
6,671 times
Add to favorites
4/19/2011
E-mail Twitter del.icio.us Digg Facebook

Solution explorer

C#
using System;
using System.Globalization;
using System.IO;
using System.Security.Cryptography;
using System.ServiceModel;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using FeedProcessor;
using FeedProcessor.Enums;
using LiveStream.MicrosoftTagService;
using LiveStream.Properties;

namespace LiveStream.Controls.RiverContent
{
    /// <summary>
    /// Interaction logic for TagBack.xaml
    /// </summary>
    public partial class TagBack : UserControl, IDisposable
    {
        /// <summary>
        /// The credential passed along to tag service requests.
        /// </summary>
        private static UserCredential _tagCredential = new UserCredential { AccessToken = Constants.MicrosoftTagApiKey };

        /// <summary>
        /// The client used for loading MS tags.
        /// </summary>
        private MicrosoftTagService.MIBPContractClient _client;

        /// <summary>
        /// The category name used for creating new tags.
        /// </summary>
        private static string _tagCategory = "Main";

        /// <summary>
        /// Whether or not the last named tag has been loaded.
        /// </summary>
        private bool _isTagLoaded;

        /// <summary>
        /// Initializes a new instance of the <see cref="TagBack"/> class.
        /// </summary>
        public TagBack()
        {
            InitializeComponent();

            // The use of Plane causes problems in resolving resources in the content that appears on the back, so we have
            // to do this and include Resources.xaml in the the TagBack control.
            Resources["ThemeColor"] = Settings.Default.ThemeColor;
            Resources["ForegroundColor"] = Settings.Default.ForegroundColor;

            DataContextChanged += new DependencyPropertyChangedEventHandler(TagBack_DataContextChanged);
        }

        /// <summary>
        /// Handles the DataContextChanged event of the TagBack control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
        private void TagBack_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            FeedItem feedItem = DataContext as FeedItem;

            if (feedItem == null)
            {
                return;
            }

            string labelState = NoLabel.Name;
            string contentTypeState = NotStatus.Name;
            if (feedItem != null)
            {
                if (feedItem.ContentType == ContentType.Image)
                {
                    labelState = ImageLabel.Name;
                }
                else if (feedItem.ContentType == ContentType.News)
                {
                    labelState = NewsLabel.Name;
                }
                else if (feedItem.ContentType == ContentType.Status)
                {
                    labelState = StatusLabel.Name;
                    contentTypeState = IsStatus.Name;
                }
            }

            VisualStateManager.GoToState(this, labelState, true);
            VisualStateManager.GoToState(this, contentTypeState, true);
        }

        /// <summary>
        /// Handles the Click event of the Close button.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Input.RoutedEventArgs"/> instance containing the event data.</param>
        private void Close_Click(object sender, RoutedEventArgs e)
        {
            RaiseEvent(new UserSourceRoutedEventArgs(RiverItemBase.CloseRequestedEvent, _closeBtn));
        }

        /// <summary>
        /// Handles the Click event of the Flip button.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Input.RoutedEventArgs"/> instance containing the event data.</param>
        private void Flip_Click(object sender, RoutedEventArgs e)
        {
            RaiseEvent(new UserSourceRoutedEventArgs(RiverContentItem.FlipRequestedEvent, _flipBtn));
        }

        /// <summary>
        /// Backing store for TagName.
        /// </summary>
        private string _tagName;

        /// <summary>
        /// Gets or sets the name of the tag to load.
        /// </summary>
        /// <value>The name of the tag.</value>
        public string TagName
        {
            get
            {
                return _tagName;
            }

            set
            {
                _tagName = value;
                _isTagLoaded = false;
            }
        }

        #region IsFlipped

        /// <summary>
        /// Gets or sets a value indicating whether this instance is flipped.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is flipped; otherwise, <c>false</c>.
        /// </value>
        public bool IsFlipped
        {
            get { return (bool)GetValue(IsFlippedProperty); }
            set { SetValue(IsFlippedProperty, value); }
        }

        /// <summary>
        /// Backing store for IsFlipped.
        /// </summary>
        public static readonly DependencyProperty IsFlippedProperty = DependencyProperty.Register(
            "IsFlipped",
            typeof(bool),
            typeof(TagBack),
            new PropertyMetadata(false, (sender, e) => (sender as TagBack).UpdateIsFlipped()));

        /// <summary>
        /// When the item is flipped, load the MS Tag.
        /// </summary>
        private void UpdateIsFlipped()
        {
            if (!IsFlipped || _isTagLoaded == true)
            {
                return;
            }

            LoadTag();
        }

        #endregion

        #region Tag Loading

        /// <summary>
        /// Begins loading the tag.
        /// </summary>
        private void LoadTag()
        {
            _tagImageHorizontal.Source = _tagImageVertical.Source = null;
            VisualStateManager.GoToState(this, TagLoading.Name, true);

            if (_client != null)
            {
                _client.Abort();
                _client.CreateTagCompleted -= Client_CreateTagCompleted;
                _client.GetBarcodeCompleted -= Client_GetBarcodeCompleted;
            }

            if (string.IsNullOrEmpty(_tagName))
            {
                return;
            }

            // Define the tag to create.
            URITag tag = new URITag
            {
                MedFiUrl = _tagName,

                // Hash the URL for use in the title, because if the URL is too long, the tag service gets angry.
                Title = GetMD5Hash(_tagName),
                UTCStartDate = DateTime.Now,
                UTCEndDate = DateTime.Now.AddYears(1)
            };

            _client = new MicrosoftTagService.MIBPContractClient();
            _client.CreateTagCompleted += Client_CreateTagCompleted;
            _client.CreateTagAsync(_tagCredential, _tagCategory, tag);
            VisualStateManager.GoToState(this, TagLoading.Name, true);
        }

        /// <summary>
        /// When the tag has been created, begin loading the image for it.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="LiveStream.MicrosoftTagService.CreateTagCompletedEventArgs"/> instance containing the event data.</param>
        private void Client_CreateTagCompleted(object sender, CreateTagCompletedEventArgs e)
        {
            _client.CreateTagCompleted -= Client_CreateTagCompleted;

            FaultException fault = e.Error as FaultException;
            if (e.Error == null || (fault != null && fault.Message.Contains("Tag with the same name already exist.")))
            {
                _client.GetBarcodeCompleted += Client_GetBarcodeCompleted;
                _client.GetBarcodeAsync(_tagCredential, _tagCategory, GetMD5Hash(_tagName), ImageTypes.png, .8f, DecorationType.HCCBRP_DECORATION_NONE, false);
                return;
            }

            _isTagLoaded = false;
            VisualStateManager.GoToState(this, TagFailed.Name, true);
        }

        /// <summary>
        /// When the image has been loaded, decode and display it.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="LiveStream.MicrosoftTagService.GetBarcodeCompletedEventArgs"/> instance containing the event data.</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Can't dispose it or the image won't show. This should happen automatically."), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Really want to catch any decode error.")]
        private void Client_GetBarcodeCompleted(object sender, GetBarcodeCompletedEventArgs e)
        {
            _client.GetBarcodeCompleted -= Client_GetBarcodeCompleted;
            if (e.Error != null)
            {
                _isTagLoaded = true;
                VisualStateManager.GoToState(this, TagFailed.Name, true);
                return;
            }

            try
            {
                BitmapSource source = new PngBitmapDecoder(new MemoryStream(e.Result), BitmapCreateOptions.None, BitmapCacheOption.Default).Frames[0];
                _tagImageHorizontal.Source = _tagImageVertical.Source = source;
                VisualStateManager.GoToState(this, ActualWidth > ActualHeight ? TagLoadedHorizontal.Name : TagLoadedVertical.Name, true);
            }
            catch
            {
                VisualStateManager.GoToState(this, TagFailed.Name, true);
            }

            _isTagLoaded = true;
        }

        /// <summary>
        /// Gets the MD5 hash of a string.
        /// </summary>
        /// <param name="input">The input.</param>
        /// <returns>The MD5 hash of a string</returns>
        private static string GetMD5Hash(string input)
        {
            using (MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider())
            {
                byte[] bytes = Encoding.UTF8.GetBytes(input);
                bytes = md5.ComputeHash(bytes);
                StringBuilder stringBuilder = new StringBuilder();
                foreach (byte b in bytes)
                {
                    stringBuilder.Append(b.ToString("x2", CultureInfo.InvariantCulture).ToUpperInvariant());
                }

                return stringBuilder.ToString();
            }
        }

        #endregion

        #region IDisposable

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_client != null)
                {
                    _client.Close();
                    _client = null;
                }
            }
        }

        #endregion
    }
}