Hub Tiles (In App Tiles) Windows Phone 8.1 (Univer

2019-09-20 17:49发布

问题:

Basic Requirement - Displaying In App tiles in Universal Apps.

I have gone through samples of Hub Tiles from the following link Hub Tiles which applies to Windows Phone 7 and 8, 8.1 (Silverlight), but there is no mentioning of windows Phone 8.1 (Universal Applications). Even if i include the assembly separately it throws an error that Microsoft.Phone cannot be resolved.

As a work around I have even downloaded the source of hub Tiles from Windows phone Toolkit Source and resolved the assemblies, modified the templates and edited it accordingly. But I might be missing on some points, Although It is showing as a control in the tool box but it is not even visible when I add it to XAML. I am adding the edited code for all the three files available from the source of the toolkit.

HubTiles.cs

    // (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.

using System.Windows;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;

namespace Microsoft.Phone.Controls
{
    /// <summary>
    /// Represents an animated tile that supports an image and a title.
    /// Furthermore, it can also be associated with a message or a notification.
    /// </summary>
    /// <QualityBand>Preview</QualityBand>
    [TemplateVisualState(Name = Expanded, GroupName = ImageStates)]
    [TemplateVisualState(Name = Semiexpanded, GroupName = ImageStates)]
    [TemplateVisualState(Name = Collapsed, GroupName = ImageStates)]
    [TemplateVisualState(Name = Flipped, GroupName = ImageStates)]
    [TemplatePart(Name = NotificationBlock, Type = typeof(TextBlock))]
    [TemplatePart(Name = MessageBlock, Type = typeof(TextBlock))]
    [TemplatePart(Name = BackTitleBlock, Type = typeof(TextBlock))]
    [TemplatePart(Name = TitlePanel, Type = typeof(Panel))]
    public class HubTile : Control
    {
        /// <summary>
        /// Common visual states.
        /// </summary>
        private const string ImageStates = "ImageState";

        /// <summary>
        /// Expanded visual state.
        /// </summary>
        private const string Expanded = "Expanded";

        /// <summary>
        /// Semiexpanded visual state.
        /// </summary>
        private const string Semiexpanded = "Semiexpanded";

        /// <summary>
        /// Collapsed visual state.
        /// </summary>
        private const string Collapsed = "Collapsed";

        /// <summary>
        /// Flipped visual state.
        /// </summary>
        private const string Flipped = "Flipped";

        /// <summary>
        /// Nofitication Block template part name.
        /// </summary>
        private const string NotificationBlock = "NotificationBlock";

        /// <summary>
        /// Message Block template part name.
        /// </summary>
        private const string MessageBlock = "MessageBlock";

        /// <summary>
        /// Back Title Block template part name.
        /// </summary>
        private const string BackTitleBlock = "BackTitleBlock";

        /// <summary>
        /// Title Panel template part name.
        /// </summary>
        private const string TitlePanel = "TitlePanel";

        /// <summary>
        /// Notification Block template part.
        /// </summary>
        private TextBlock _notificationBlock;

        /// <summary>
        /// Message Block template part.
        /// </summary>
        private TextBlock _messageBlock;

        /// <summary>
        /// Title Panel template part.
        /// </summary>
        private Panel _titlePanel;

        /// <summary>
        /// Back Title Block template part.
        /// </summary>
        private TextBlock _backTitleBlock;

        /// <summary>
        /// Represents the number of steps inside the pipeline of stalled images
        /// </summary>
        internal int _stallingCounter;

        /// <summary>
        /// Flag that determines if the hub tile has a primary text string associated to it.
        /// If it does not, the hub tile will not drop.
        /// </summary>
        internal bool _canDrop;

        /// <summary>
        /// Flag that determines if the hub tile has a secondary text string associated to it.
        /// If it does not, the hub tile will not flip.
        /// </summary>
        internal bool _canFlip;

        #region Source DependencyProperty

        /// <summary>
        /// Gets or sets the image source.
        /// </summary>
        public ImageSource Source
        {
            get { return (ImageSource)GetValue(SourceProperty); }
            set { SetValue(SourceProperty, value); }
        }

        /// <summary>
        /// Identifies the Source dependency property.
        /// </summary>
        public static readonly DependencyProperty SourceProperty =
            DependencyProperty.Register("Source", typeof(ImageSource), typeof(HubTile), new PropertyMetadata(null));

        #endregion

        #region Title DependencyProperty

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

        /// <summary>
        /// Identifies the Title dependency property.
        /// </summary>
        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register("Title", typeof(string), typeof(HubTile), new PropertyMetadata(string.Empty, new PropertyChangedCallback(OnTitleChanged)));

        /// <summary>
        /// Prevents the hub tile from transitioning into a Semiexpanded or Collapsed visual state if the title is not set.
        /// </summary>
        /// <param name="obj">The dependency object.</param>
        /// <param name="e">The event information.</param>
        private static void OnTitleChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            HubTile tile = (HubTile)obj;

            if (string.IsNullOrEmpty((string)e.NewValue))
            {
                tile._canDrop = false;
                tile.State = ImageState.Expanded;
            }
            else
            {
                tile._canDrop = true;
            }
        }

        #endregion

        #region Notification DependencyProperty

        /// <summary>
        /// Gets or sets the notification alert.
        /// </summary>
        public string Notification
        {
            get { return (string)GetValue(NotificationProperty); }
            set { SetValue(NotificationProperty, value); }
        }

        /// <summary>
        /// Identifies the Notification dependency property.
        /// </summary>
        public static readonly DependencyProperty NotificationProperty =
            DependencyProperty.Register("Notification", typeof(string), typeof(HubTile), new PropertyMetadata(string.Empty, new PropertyChangedCallback(OnBackContentChanged)));

        /// <summary>
        /// Prevents the hub tile from transitioning into a Flipped visual state if neither the notification alert nor the message are set.
        /// </summary>
        /// <param name="obj">The dependency object.</param>
        /// <param name="e">The event information.</param>
        private static void OnBackContentChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            HubTile tile = (HubTile)obj;

            // If there is a new notification or a message, the hub tile can flip.
            if ((!(string.IsNullOrEmpty(tile.Notification)) && tile.DisplayNotification) 
                || (!(string.IsNullOrEmpty(tile.Message)) && !tile.DisplayNotification))
            {
                tile._canFlip = true;
            }
            else
            {
                tile._canFlip = false;
                tile.State = ImageState.Expanded;
            }
        }

        #endregion

        #region Message DependencyProperty

        /// <summary>
        /// Gets or sets the message.
        /// </summary>
        public string Message
        {
            get { return (string)GetValue(MessageProperty); }
            set { SetValue(MessageProperty, value); }
        }

        /// <summary>
        /// Identifies the Message dependency property.
        /// </summary>
        public static readonly DependencyProperty MessageProperty =
            DependencyProperty.Register("Message", typeof(string), typeof(HubTile), new PropertyMetadata(string.Empty, new PropertyChangedCallback(OnBackContentChanged)));

        #endregion

        #region DisplayNotification DependencyProperty

        /// <summary>
        /// Gets or sets the flag for new notifications.
        /// </summary>
        public bool DisplayNotification
        {
            get { return (bool)GetValue(DisplayNotificationProperty); }
            set { SetValue(DisplayNotificationProperty, value); }
        }

        /// <summary>
        /// Identifies the DisplayNotification dependency property.
        /// </summary>
        public static readonly DependencyProperty DisplayNotificationProperty =
            DependencyProperty.Register("DisplayNotification", typeof(bool), typeof(HubTile), new PropertyMetadata(false, new PropertyChangedCallback(OnBackContentChanged)));

        #endregion

        #region IsFrozen DependencyProperty

        /// <summary>
        /// Gets or sets the flag for images that do not animate.
        /// </summary>
        public bool IsFrozen
        {
            get { return (bool)GetValue(IsFrozenProperty); }
            set { SetValue(IsFrozenProperty, value); }
        }

        /// <summary>
        /// Identifies the IsFrozen dependency property.
        /// </summary>
        public static readonly DependencyProperty IsFrozenProperty =
            DependencyProperty.Register("IsFrozen", typeof(bool), typeof(HubTile), new PropertyMetadata(false, new PropertyChangedCallback(OnIsFrozenChanged)));

        /// <summary>
        /// Removes the frozen image from the enabled image pool or the stalled image pipeline.
        /// Adds the non-frozen image to the enabled image pool.  
        /// </summary>
        /// <param name="obj">The dependency object.</param>
        /// <param name="e">The event information.</param>
        private static void OnIsFrozenChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            HubTile tile = (HubTile)obj;

            if ((bool)e.NewValue)
            {
                HubTileService.FreezeHubTile(tile);
            }
            else
            {
                HubTileService.UnfreezeHubTile(tile);
            }
        }

        #endregion

        #region GroupTag DependencyProperty

        /// <summary>
        /// Gets or sets the group tag.
        /// </summary>
        public string GroupTag
        {
            get { return (string)GetValue(GroupTagProperty); }
            set { SetValue(GroupTagProperty, value); }
        }

        /// <summary>
        /// Identifies the GroupTag dependency property.
        /// </summary>
        public static readonly DependencyProperty GroupTagProperty =
            DependencyProperty.Register("GroupTag", typeof(string), typeof(HubTile), new PropertyMetadata(string.Empty));

        #endregion

        #region State DependencyProperty

        /// <summary>
        /// Gets or sets the visual state.
        /// </summary>
        internal ImageState State
        {
            get { return (ImageState)GetValue(StateProperty); }
            set { SetValue(StateProperty, value); }
        }

        /// <summary>
        /// Identifies the State dependency property.
        /// </summary>
        private static readonly DependencyProperty StateProperty =
                DependencyProperty.Register("State", typeof(ImageState), typeof(HubTile), new PropertyMetadata(ImageState.Expanded, OnImageStateChanged));

        /// <summary>
        /// Triggers the transition between visual states.
        /// </summary>
        /// <param name="obj">The dependency object.</param>
        /// <param name="e">The event information.</param>
        private static void OnImageStateChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            ((HubTile)obj).UpdateVisualState();
        }

        #endregion

        #region Size DependencyProperty

        /// <summary>
        /// Gets or sets the visual state.
        /// </summary>
        public TileSize Size
        {
            get { return (TileSize)GetValue(SizeProperty); }
            set { SetValue(SizeProperty, value); }
        }

        /// <summary>
        /// Identifies the State dependency property.
        /// </summary>
        public static readonly DependencyProperty SizeProperty =
                DependencyProperty.Register("Size", typeof(TileSize), typeof(HubTile), new PropertyMetadata(TileSize.Default, OnSizeChanged));

        /// <summary>
        /// Triggers the transition between visual states.
        /// </summary>
        /// <param name="obj">The dependency object.</param>
        /// <param name="e">The event information.</param>
        private static void OnSizeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            HubTile hubTile = (HubTile)obj;

            // And now we'll update the width and height to match the new size.
            switch (hubTile.Size)
            {
                case TileSize.Default:
                    hubTile.Width = 173;
                    hubTile.Height = 173;
                    break;

                case TileSize.Small:
                    hubTile.Width = 99;
                    hubTile.Height = 99;
                    break;

                case TileSize.Medium:
                    hubTile.Width = 210;
                    hubTile.Height = 210;
                    break;

                case TileSize.Large:
                    hubTile.Width = 432;
                    hubTile.Height = 210;
                    break;
            }

            hubTile.SizeChanged += OnHubTileSizeChanged;
            HubTileService.FinalizeReference(hubTile);
        }

        static void OnHubTileSizeChanged(object sender, SizeChangedEventArgs e)
        {
            HubTile hubTile = (HubTile)sender;
            hubTile.SizeChanged -= OnHubTileSizeChanged;

            // In order to avoid getting into a bad state, we'll shift the HubTile
            // back to the Expanded state.  If we were already in the Expanded state,
            // then we'll manually shift the title panel to the right location,
            // since the visual state manager won't do it for us in that case.
            if (hubTile.State != ImageState.Expanded)
            {
                hubTile.State = ImageState.Expanded;
                VisualStateManager.GoToState(hubTile, Expanded, false);
            }
            else if (hubTile._titlePanel != null)
            {
                CompositeTransform titlePanelTransform = hubTile._titlePanel.RenderTransform as CompositeTransform;

                if (titlePanelTransform != null)
                {
                    titlePanelTransform.TranslateY = -hubTile.Height;
                }
            }

            HubTileService.InitializeReference(hubTile);
        }

        #endregion

        /// <summary>
        /// Updates the visual state.
        /// </summary>
        private void UpdateVisualState()
        {
            string state;

            // If we're in the Small size, then we should just display the image
            // instead of having animations.
            if (Size != TileSize.Small)
            {
                switch (State)
                {
                    case ImageState.Expanded:
                        state = Expanded;
                        break;
                    case ImageState.Semiexpanded:
                        state = Semiexpanded;
                        break;
                    case ImageState.Collapsed:
                        state = Collapsed;
                        break;
                    case ImageState.Flipped:
                        state = Flipped;
                        break;
                    default:
                        state = Expanded;
                        break;
                }
            }
            else
            {
                state = Expanded;
            }

            VisualStateManager.GoToState(this, state, true);
        }

        /// <summary>
        /// Gets the template parts and sets binding.
        /// </summary>
        protected override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            _notificationBlock = base.GetTemplateChild(NotificationBlock) as TextBlock;
            _messageBlock = base.GetTemplateChild(MessageBlock) as TextBlock;
            _backTitleBlock = base.GetTemplateChild(BackTitleBlock) as TextBlock;
            _titlePanel = base.GetTemplateChild(TitlePanel) as Panel;

            //Do binding in code to avoid exposing unnecessary value converters.
            if (_notificationBlock != null)
            {                
                Binding bindVisible = new Binding();
                bindVisible.Source = this;
                bindVisible.Path = new PropertyPath("DisplayNotification");
                bindVisible.Converter = new VisibilityConverter();
                bindVisible.ConverterParameter = false;
                _notificationBlock.SetBinding(TextBlock.VisibilityProperty, bindVisible);
            }

            if(_messageBlock != null)
            {
                Binding bindCollapsed = new Binding();
                bindCollapsed.Source = this;
                bindCollapsed.Path = new PropertyPath("DisplayNotification");
                bindCollapsed.Converter = new VisibilityConverter();
                bindCollapsed.ConverterParameter = true;
                _messageBlock.SetBinding(TextBlock.VisibilityProperty, bindCollapsed);
            }

            if(_backTitleBlock != null)
            {
                Binding bindTitle = new Binding();
                bindTitle.Source = this;
                bindTitle.Path = new PropertyPath("Title");
                bindTitle.Converter = new MultipleToSingleLineStringConverter();
                _backTitleBlock.SetBinding(TextBlock.TextProperty, bindTitle);
            }

            UpdateVisualState();            
        }

        /// <summary>
        /// Initializes a new instance of the HubTile class.
        /// </summary>
        public HubTile()
        {
            DefaultStyleKey = typeof(HubTile);
            Loaded += HubTile_Loaded;
            Unloaded += HubTile_Unloaded;
        }

        /// <summary>
        /// This event handler gets called as soon as a hub tile is added to the visual tree.
        /// A reference of this hub tile is passed on to the service singleton.
        /// </summary>
        /// <param name="sender">The hub tile.</param>
        /// <param name="e">The event information.</param>
        void HubTile_Loaded(object sender, RoutedEventArgs e)
        {
            HubTileService.InitializeReference(this);
        }

        /// <summary>
        /// This event handler gets called as soon as a hub tile is removed from the visual tree.
        /// Any existing reference of this hub tile is eliminated from the service singleton.
        /// </summary>
        /// <param name="sender">The hub tile.</param>
        /// <param name="e">The event information.</param>
        void HubTile_Unloaded(object sender, RoutedEventArgs e)
        {
            HubTileService.FinalizeReference(this);
        }        
    }

    /// <summary>
    /// Represents the visual states of a Hub tile.
    /// </summary>
    internal enum ImageState
    {
        /// <summary>
        /// Expanded visual state value.
        /// </summary>
        Expanded = 0,

        /// <summary>
        /// Semiexpanded visual state value.
        /// </summary>
        Semiexpanded = 1,

        /// <summary>
        /// Collapsed visual state value.
        /// </summary>
        Collapsed = 2,

        /// <summary>
        /// Flipped visual state value.
        /// </summary>
        Flipped = 3,
    };

    /// <summary>
    /// Represents the size of a Hub tile.
    /// </summary>
    public enum TileSize
    {
        /// <summary>
        /// Default size (173 px x 173 px).
        /// </summary>
        Default,

        /// <summary>
        /// Small size (99 px x 99 px).
        /// </summary>
        Small,

        /// <summary>
        /// Medium size (210 px x 210 px).
        /// </summary>
        Medium,

        /// <summary>
        /// Large size (432 px x 210 px).
        /// </summary>
        Large,
    };
}

Note: We can edit the same for HubTileConverters and HubTileService but still it doesnt work.

If any one has a solution or has edited the same for Universal Application Or if there is any Toolkit from Microsoft for the same then please let me know.

TIA.

回答1:

I have ported the toolkit HubTile stuff. Done with a sample for your refrence please find in the following link.

HubTile sample for universal app

Hope this will help you.



回答2:

Maybe you should check the Generic.xaml file in toolkit source code, it is placed in Themes folder. All toolkit control default styles are stored in this file. It seems your problem is lack of this style file.

Because HubTile is a custom control, it will read the \Themes\Generic.xaml in solution by using DefaultStyleKey = typeof(HubTile) in its constructor. You should port this file to your solution.