Social Stream for Microsoft Surface 是微软与Stimulant, Inc协作创建的一个简单的应用程序示例,此示例程序可以把社区的照片、tweets通过这个应用程序流畅的触摸和翻动分享给大家,值得我们一览。
示例中的代码:RiverContentItem.cs
using System;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
using FeedProcessor;
using FeedProcessor.Enums;
using FeedProcessor.FeedItems;
using Microsoft.Surface.Presentation.Controls;
using SocialStream.Controls.RiverContent;
using SocialStream.Helpers;
using SocialStream.Properties;
namespace SocialStream.Controls
{
/// <summary>
/// Represents a content item in the river. Manages the display of content within itself and transitions between large and small content.
/// </summary>
internal class RiverContentItem : RiverItemBase
{
#region Private fields
/// <summary>
/// The content to display when the first half of the flash animation completes.
/// </summary>
private UserControl _nextState;
/// <summary>
/// The current item being rendered.
/// </summary>
private FeedItem _feedItem;
/// <summary>
/// The renderer for ImageFeedItems when in the river.
/// </summary>
private SmallImage _smallImage;
/// <summary>
/// The renderer for NewsFeedItems when in the river.
/// </summary>
private SmallNews _smallNews;
/// <summary>
/// The renderer for StatusFeedItems when in the river.
/// </summary>
private SmallTweet _smallTweet;
/// <summary>
/// The button to ban a user.
/// </summary>
private SurfaceButton _banBtn;
/// <summary>
/// The button to delete a specific item.
/// </summary>
private SurfaceButton _deleteBtn;
/// <summary>
/// An animation shown for especially new items.
/// </summary>
private Storyboard _breaking;
/// <summary>
/// The ItemProxy that this item is a part of.
/// </summary>
private ItemProxy _parentProxy;
#endregion
/// <summary>
/// When overridden in a derived class, is invoked whenever application code or internal processes call <see cref="M:System.Windows.FrameworkElement.ApplyTemplate"/>.
/// </summary>
public override void OnApplyTemplate()
{
_smallImage = GetTemplateChild("PART_SmallImage") as SmallImage;
_smallNews = GetTemplateChild("PART_SmallNews") as SmallNews;
_smallTweet = GetTemplateChild("PART_SmallTweet") as SmallTweet;
_banBtn = GetTemplateChild("PART_BanBtn") as SurfaceButton;
_deleteBtn = GetTemplateChild("PART_DeleteBtn") as SurfaceButton;
_banBtn.Click += AdminBtn_Click;
_deleteBtn.Click += AdminBtn_Click;
_breaking = (Template.Resources["Breaking"] as Storyboard).Clone();
_parentProxy = this.FindVisualParent<ItemProxy>();
if (_parentProxy != null)
{
_smallImage.Image.ImageLoaded += (sender, e) => _parentProxy.IsEnabled = true;
}
base.OnApplyTemplate();
}
#region RiverItemBase
/// <summary>
/// Called by the river when the item should retrieve data from its data source.
/// </summary>
/// <param name="state">A definition which describes the size and position of this item in the river.</param>
/// <param name="maintainUnblockedData">if set to <c>true</c> [maintain unblocked data].</param>
/// <returns>
/// The data that this item will render. If null, the item won't be shown.
/// </returns>
internal override object GetData(RiverItemState state, bool maintainUnblockedData)
{
if (DesignerProperties.GetIsInDesignMode(this))
{
return new object();
}
else if (AppState.Instance.FeedProcessor != null)
{
if (maintainUnblockedData && _feedItem != null && _feedItem.BlockReason == BlockReason.None)
{
return _feedItem;
}
FeedItem feedItem = null;
if (state.RowSpan == state.ColumnSpan)
{
// If it's square, be an image.
feedItem = AppState.Instance.FeedProcessor.GetNextItem(ContentType.Image);
}
else
{
// If not, be twitter or news.
feedItem = AppState.Instance.FeedProcessor.GetNextItem(ContentType.Status | ContentType.News);
}
return feedItem;
}
return null;
}
/// <summary>
/// Called by the river when the item should render some data.
/// </summary>
/// <param name="state">A definition which describes the size and position of this item in the river.</param>
/// <param name="data">The data that the river is requesting to be rendered. The item can override this and return different data if needed.</param>
/// <returns>
/// The data that this item will render. If null, the item won't be shown.
/// </returns>
internal override object RenderData(RiverItemState state, object data)
{
UserControl visualState = null;
object finalData = data;
if (DesignerProperties.GetIsInDesignMode(this))
{
if (state.RowSpan == state.ColumnSpan)
{
visualState = _smallImage;
}
else if (App.Random.NextDouble() > .5)
{
visualState = _smallNews;
}
else
{
visualState = _smallTweet;
}
}
else if (AppState.Instance.IsInitialized)
{
_feedItem = data as FeedItem;
if (_feedItem != null && _feedItem.BlockReason != BlockReason.None)
{
// This object is being rendered from history, but it got blocked since it was last displayed. Reject this content and get new content.
finalData = _feedItem = GetData(state, false) as FeedItem;
}
if (_feedItem is ImageFeedItem)
{
// visualState = removed ? _largeImage as UserControl : _smallImage as UserControl;
visualState = _smallImage as UserControl;
}
else if (_feedItem is NewsFeedItem)
{
// visualState = removed ? _largeNews as UserControl : _smallNews as UserControl;
visualState = _smallNews as UserControl;
}
else if (_feedItem is StatusFeedItem)
{
// visualState = removed ? _largeTweet as UserControl : _smallTweet as UserControl;
visualState = _smallTweet as UserControl;
}
DataContext = _feedItem;
if (_feedItem is ImageFeedItem && _parentProxy != null)
{
// Disable the item while it's loading.
_parentProxy.IsEnabled = _smallImage.Image.BitmapImage != null;
}
_banBtn.Visibility = _feedItem != null && !string.IsNullOrEmpty(_feedItem.Author) ? Visibility.Visible : Visibility.Hidden;
}
GoToState(visualState);
if (_feedItem != null && DateTime.Now - _feedItem.Date <= Settings.Default.NewItemAlert)
{
// Show the "breaking" animation for new items.
_breaking.Begin(this, Template, true);
}
return finalData;
}
/// <summary>
/// Called by the river when this item is being hidden because it scrolled out of view.
/// </summary>
internal override void Cleanup()
{
_feedItem = null;
_breaking.Stop(this);
DataContext = null;
}
/// <summary>
/// Called when the item is removed from the river by the user.
/// </summary>
/// <returns>Sizing restrictions for the item once its in the river.</returns>
internal override RiverSize Removed()
{
RiverSize riverSize = new RiverSize { MaxSize = DesiredSize, RemovedSize = DesiredSize, MinSize = DesiredSize };
return riverSize;
}
/// <summary>
/// Called when the item has been removed from the river and its growth animation has completed.
/// </summary>
internal override void RemoveFinished()
{
}
/// <summary>
/// Called when the item is added back to the river due to a timeout.
/// </summary>
internal override void Added()
{
_nextState = null;
if (_feedItem is ImageFeedItem)
{
_nextState = _smallImage;
}
else if (_feedItem is NewsFeedItem)
{
_nextState = _smallNews;
}
else if (_feedItem is StatusFeedItem)
{
_nextState = _smallTweet;
}
if (_feedItem != null && DateTime.Now - _feedItem.Date <= Settings.Default.NewItemAlert)
{
// Show the "breaking" animation for new items.
_breaking.Begin(this, Template, true);
}
}
#endregion
/// <summary>
/// When the "flash" animation completes, populate the new content and play the second half of the animation.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void Flash_Completed(object sender, EventArgs e)
{
GoToState(_nextState);
_nextState = null;
}
/// <summary>
/// Toggle the visibility of the content renderers.
/// This should probably be done with VSM, but I always have trouble with it in WPF custom controls...
/// </summary>
/// <param name="state">The content renderer to show.</param>
private void GoToState(UserControl state)
{
_smallImage.Visibility = state == _smallImage ? Visibility.Visible : Visibility.Hidden;
_smallNews.Visibility = state == _smallNews ? Visibility.Visible : Visibility.Hidden;
_smallTweet.Visibility = state == _smallTweet ? Visibility.Visible : Visibility.Hidden;
if (state != null)
{
state.DataContext = _feedItem;
}
}
#region IsAdminTagPresent
/// <summary>
/// Gets or sets a value indicating whether the admin tag is present.
/// </summary>
/// <value>
/// <c>true</c> if the admin tag is present; otherwise, <c>false</c>.
/// </value>
public bool IsAdminTagPresent
{
get { return (bool)GetValue(IsAdminTagPresentProperty); }
set { SetValue(IsAdminTagPresentProperty, value); }
}
/// <summary>
/// Identifies the IsAdminTagPresent dependency property.
/// </summary>
public static readonly DependencyProperty IsAdminTagPresentProperty = DependencyProperty.Register("IsAdminTagPresent", typeof(bool), typeof(RiverContentItem), new PropertyMetadata(false));
#endregion
/// <summary>
/// Handles the Click event of the admin buttons. Adds a ban to the FeedProcessor queries.
/// </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 AdminBtn_Click(object sender, RoutedEventArgs e)
{
if (_feedItem == null || !AppState.Instance.IsInitialized)
{
return;
}
if (sender == _deleteBtn)
{
AppState.Instance.AddBan(_feedItem.SourceType, string.Format(CultureInfo.InvariantCulture, "{0}", _feedItem.Uri.AbsoluteUri));
}
else if (sender == _banBtn)
{
AppState.Instance.AddBan(_feedItem.SourceType, string.Format(CultureInfo.InvariantCulture, "{0}{1}", Processor.AuthorQueryMarker, _feedItem.Author));
}
RaiseEvent(new RoutedEventArgs(RiverItemBase.RefreshRequestedEvent));
}
}
}
转载时须注明本文的详细链接,否则作者将保留追究其法律责任。