2012-01-13 51 views
0

我是c#和WinPhone7开发人员的新手,如果有人能这么友善,需要一点指导,所以请原谅我的无知。创建不同宽度单元格的滚动网格

我遇到的问题是我需要为电视指南创建一个网格视图,其中您有一个垂直滚动上下滚动左侧的频道徽标列表,右侧有一个水平和垂直滚动网格。水平滚动不会移动固定在屏幕上的频道徽标,但垂直滚动网格也会像您期望的那样滚动徽标。

我应该继续尝试使用XAML和Silverlight来做到这一点,还是应该通过XNA来做到这一点?

我问,因为我曾试图通过Silverlight的几种不同的方法得到了两个主要问题,我有:

性能

当我接收使用异步请求我创建一个从我们的API数据后台工作线程解析JSON并使用Dispatch.Invoke在网格“画布”视图上创建程序单元。发生这种情况时,没有逐步的反馈,整个过程等待,直到一切完成,然后突然出现电网。我希望单元格能够按频道或逐个单元格的频道显示,而不会阻止用户界面,因此滚动效果仍然很好,但这似乎不会发生。

我遇到了问题,因为任何使用UIElements的工作都是在UI线程上完成的,WinPhone7是主线程(我相信),这包括解析XAML或创建/修改UIElements,即使它们没有添加到任何屏幕或可见。这意味着我无法通过预先创建或重新使用元素来改进内容。

我已经尽可能在工作线程中做了很多工作,只是将UI工作的一小部分分派到UI线程以尽量减少阻塞,并且它似乎没有帮助。

内存

显然我不能为潜在的数以百计的每个电视节目的事件创建“节目单元格”(我们支持超过650个频道)7天的手机将运行得非常快的内存;所以我想创建一个虚拟网格,其中单元格被创建,并且仅为当前可见的视口加载到画布视图中。

我有两个问题:

  1. 做任何UI工作的UI阻塞停止任何滚动的上方,从而创造在后台新的细胞将被滚动到视图不能发生,而不会阻塞UI
  2. 滚动视图没有发送滚动事件,我已经尝试绑定到滚动视图中的滚动条来获取偏移量值,但是这不起作用,因为它只是在适合和启动更新,所以如果你做很多滚动,直到出现暂停或OnIdle,我才会发送任何内容。

难道是我搞砸了,所以我应该坚持下去,还是我正在做一些不能做的事情,我应该尝试一种不同的方式,像通过XNA做它?

任何意见将不胜感激。

编辑:更多的信息和一些示例代码

我有一个包含内容:开始时间和标题,有名称和标志等,但也计划阵列的通道类程序类。

当我检索我的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

这个答案是_really_难,特别是如果你不给我们提供有问题的代码。尽管听起来你应该可以在没有XNA的情况下做到这一点,只要你摆脱那个丑陋的面板事件(提示:名字以'C'开始),只要你做了任何事情就会完全摧毁你的表现比在左上角显示静态项目更复杂;) – Nuffin 2012-01-13 21:59:39

+0

当用户滚动到列表结尾教程时加载数据:http://danielvaughan.orpius.com/post/Scroll-Based-Data-Loading- in-Windows-Phone-7.aspx – Ku6opr 2012-01-14 08:56:33

+0

@Tobias我已经添加了一些代码;此示例删除了我使用的所有堆叠面板(这是我可以想到的创建垂直滚动通道徽标面板和单独的水平和垂直滚动的网格面板的唯一方法),但速度绝对没有差异。如果我在数据处理过程中滚动浏览,则会进行分裂并停止,然后突然显示整个网格...没有逐渐呈现并且没有平滑的UI发生 – Dan 2012-01-14 19:08:05

回答

1

首先,采用大Canvas应该只是最后的手段 - 与MarginGridStackPanel(有时内的其他StackPanel S)大多数情况下,组合和项目会快很多(它们会虽然稍微难以处理)。

为了让应用程序响应你可以

  1. 只有一次加载数据的小块(如,例如,两页。这将大大减少数据被同时呈现的量)。然后,您可以立即加载下一个块,或者当用户在列表的末尾滚动时加载下一个块。
  2. 降低结果处理速度。如果在插入每个项目后(或每个频道后1秒钟,等待100毫秒),如果您想要一次加载频道,则对响应速度的影响应该几乎消失,同时不会对加载时间造成太大影响。所提及的时间只是估计,如果他们太大/小可随意根据您的需求进行调整以提供流畅的用户体验。
+0

谢谢。我被理解为元素的堆叠负载实际上会更糟,因此被告知画布会更好。使用堆叠的元素网格很难做到这一点,因为如果在一行中有许多程序之前在多行上绘制单元格时,难以排列它们(我首先尝试了这一点,很多问题都出现在画布上,因为它在定位上更加精确)。我会尽量延迟处理;我再次尝试了其中一次尝试,但会再次尝试。 – Dan 2012-01-14 21:13:12

+0

添加一个小Thread.Sleep的工作,并给了一些空闲时间来更新的东西。希望我会得到更多的滚动属性事件,以便我可以虚拟化它。谢谢。 – Dan 2012-01-14 23:12:14