据我所知,创建自定义位图是可行的方法。我发现这个答案和这篇文章在我做动态图块时非常有帮助。
如果您不介意购买第三方控件,您可以查看 Telerik 的 LiveTileHelper 控件(如果您是诺基亚开发者计划的成员,您已经可以使用它)。
对于我的第一个应用程序,我选择基于前两个链接推出自己的解决方案。我有一个基类来处理获取一个FrameworkElement
(每个派生类负责生成FrameworkElement
包含要呈现的信息的)并创建相应的WritableBitmap
实例,然后我使用 ToolStack C# PNG Writer Library 将其保存为 .PNG 的工作。
例如,这是我的代码,用于在我的一个应用程序中生成代表一个小的固定辅助磁贴的控件:
/// <summary>
/// Returns the fully populated and initialized control that displays
/// the information that should be included in the tile image.
/// </summary>
/// <remarks>
/// We manually create the control in code instead of using a user control
/// to avoid having to use the XAML parser when we do this work in our
/// background agent.
/// </remarks>
/// <returns>
/// The fully populated and initialized control that displays
/// the information that should be included in the tile image.
/// </returns>
protected override FrameworkElement GetPopulatedTileImageControl()
{
var layoutRoot = new Grid()
{
Background = new System.Windows.Media.SolidColorBrush( System.Windows.Media.Color.FromArgb( 0, 0, 0, 0 ) ),
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch,
Height = TileSize.Height,
Width = TileSize.Width,
Margin = new Thickness( 0, 12, 0, 0 )
};
var stopName = new TextBlock()
{
Text = Stop.Description,
TextTrimming = TextTrimming.WordEllipsis,
TextWrapping = TextWrapping.Wrap,
Margin = new Thickness( 7, 0, 7, 12 ),
MaxHeight = 135,
Width = TileSize.Width - 14,
VerticalAlignment = VerticalAlignment.Bottom,
HorizontalAlignment = HorizontalAlignment.Stretch,
FontFamily = (System.Windows.Media.FontFamily) Application.Current.Resources[ "PhoneFontFamilySemiBold" ],
FontSize = (double) Application.Current.Resources[ "PhoneFontSizeMediumLarge" ],
Style = (Style) Application.Current.Resources[ "PhoneTextNormalStyle" ]
};
Grid.SetColumn( stopName, 0 );
Grid.SetRow( stopName, 0 );
layoutRoot.Children.Add( stopName );
return layoutRoot;
}
这是一个超级简单的控件,只有一个TextBlock
,但您可以轻松地对此进行扩展。请注意,我在这里不使用 a UserControl
,因为我也在后台代理中运行此代码,您有很大的内存限制。
一旦我有了一个控件,我就会生成一个WritableBitmap
这样的:
/// <summary>
/// Renders the tile image to a <see cref="WritableBitmap"/> instance.
/// </summary>
/// <returns>
/// A <see cref="WritableBitmap"/> instance that contains the rendered
/// tile image.
/// </returns>
private WriteableBitmap RenderTileImage()
{
var tileControl = GetPopulatedTileImageControl();
var controlSize = new Size( TileSize.Width, TileSize.Height );
var tileImage = new WriteableBitmap( (int) TileSize.Width, (int) TileSize.Height );
// The control we're rendering must never be smaller than the tile
// we're generating.
tileControl.MinHeight = TileSize.Height;
tileControl.MinWidth = TileSize.Width;
// Force layout to take place.
tileControl.UpdateLayout();
tileControl.Measure( TileSize );
tileControl.Arrange( new Rect( new Point( 0, 0 ), TileSize ) );
tileControl.UpdateLayout();
tileImage.Render( tileControl, null );
tileImage.Invalidate();
tileControl = null;
GC.Collect( 2, GCCollectionMode.Forced, true );
// Adjust the rendered bitmap to handle the alpha channel better.
CompensateForRender( tileImage );
return tileImage;
}
同样,当将此代码作为后台代理的一部分运行时,我会进行显式调用以GC.Collect
帮助控制内存消耗。该CompensateForRender
方法基于链接文章中的代码。
希望这可以帮助。