我是c#和WinPhone7开发的新手,如果有人可以如此友善,需要一些指导,所以请原谅我的无知。
我遇到的问题是我需要为电视指南创建一个网格视图,其中左侧有一个垂直的通道标识列表,可以向上和向下滚动,右侧我们有一个水平和垂直滚动的网格。水平滚动不会移动固定在屏幕上的频道徽标,但垂直滚动网格也会按照您的预期滚动徽标。
我是否应继续尝试使用XAML和Silverlight进行此操作,还是应该通过XNA进行此操作?
我问,因为我已经通过Silverlight尝试了几种不同的方法来解决我遇到的两个主要问题:
性能
当我使用ASync请求从API接收数据时,我创建了一个后台工作线程,该线程解析JSON并使用Dispatch.Invoke在网格“画布”视图上创建程序单元。当这种情况发生时,没有渐进的反馈,整个事情等待一切都完成然后突然出现网格。我希望单元格逐个通道或逐个单元地显示,而不会阻止UI,因此滚动仍然可以正常工作,但这似乎不会发生。
我遇到问题,因为使用UIElements的任何工作都是在UI线程上完成的,在WinPhone7上是主线程(我相信),这包括解析XAML或创建/修改UIElements,即使它们没有被添加到任何东西上 - 屏幕或可见。这意味着我无法通过预先创建或重新使用元素来改进。
我已尝试在工作线程中尽可能多地执行操作,并且只是将一小部分UI工作分派到UI线程以最小化阻塞,并且它似乎没有帮助。
内存
很明显,我不能为每个电视节目活动创建'节目单元',因为手机内存很快就会耗尽数百天(我们支持650多个频道)。所以我想创建一个虚拟网格,其中创建单元格并将其加载到画布视图中,仅用于当前看到的视口。
我有两个问题:
是不是搞砸了,我是否应该坚持下去,或者我正在做一些无法完成的事情,我应该尝试不同的机智,比如通过XNA做这件事?
非常感谢任何建议。
编辑:更多信息和一些示例代码
我有一个Program类,其中包含开始时间和标题,具有名称和徽标等的Channel类,以及一系列程序。
当我检索我的API数据时,我创建了一个通道对象并将其添加到一个通道数组中,然后我将程序添加到通道程序数组中。将通道的所有程序添加到数组后,我将其发布到ChannelProgrammesComplete事件侦听器,以便更新UI。
<ScrollViewer ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollBarVisibility="Visible">
<Canvas x:Name="ProgGrid"
Height="55" Width="393"
VerticalAlignment="Top" HorizontalAlignment="Left">
</Canvas>
</ScrollViewer>
public void ChannelProgrammesComplete( object sender, EventArgs e )
{
var bw = new BackgroundWorker();
bw.WorkerReportsProgress = true;
bw.DoWork += ( doWorkSender, args ) =>
{
Dispatch( (Channel)sender );
};
bw.RunWorkerAsync();
}
private void Dispatch( BackgroundWorker bw, object param )
{
Channel channel = (Channel)param;
int progCount = 0;
foreach( Programme programme in channel.Programmes )
{
double left = ( ( programme.StartSecsFromToday / 60 ) * PixelsPerMinute ); // turn it into seconds
if( progCount == 0 && left < 0 )
{
// If first prog starts before 6am, shrink the cell so it starts at the 6am start point
programme.UIWidth = ( ( programme.Duration - ( ( programme.StartSecsFromToday / 60 ) * -1 ) ) * PixelsPerMinute ) - _cellPadding;
left = 0;
}
else
{
programme.UIWidth = ( programme.Duration * PixelsPerMinute ) - _cellPadding; // Multiply by zoom level which is 3 for now, and take off the amount we use for right margin grid separator
}
Debug.Assert( programme.UIWidth > 0 );
programme.UITop = channel.SortIndex * ( _rowHeight + _cellPadding );
programme.UILeft = left;
programme.UIHeight = _rowHeight;
object[] invokeArgs = new object[ 1 ];
invokeArgs[ 0 ] = programme;
// Do as much work as possible in the thread before dispatching to the UI thread for the simple UI work
Dispatcher.BeginInvoke( new InvokeProgrammeCellDelegate( AddProgrammeCellDelegate ), invokeArgs );
}
}
public delegate void InvokeProgrammeCellDelegate( Programme prog );
public void AddProgrammeCellDelegate( Programme prog )
{
Rectangle progCell = new Rectangle();
progCell.Fill = new SolidColorBrush( Color.FromArgb( 0xFF, (byte)( 0x13 ), (byte)( 0x45 ), (byte)( 0x70 ) ) );
progCell.Height = prog.UIHeight;
progCell.Width = prog.UIWidth;
progCell.SetValue( Canvas.TopProperty, prog.UITop );
progCell.SetValue( Canvas.LeftProperty, prog.UILeft );
ProgGrid.Children.Add( progCell );
ProgGrid.Width = Math.Max( ProgGrid.Width, prog.UIWidth + prog.UILeft );
}
答案 0 :(得分:1)
首先,使用大Canvas
应该只是最后的选择 - 在大多数情况下,Grid
或StackPanel
的组合(有时在其他StackPanel
内)和具有Margin
的项目会快得多(虽然它们会稍微难以处理)。
要让应用程序保持响应,您可以