Note that there are some explanatory texts on larger screens.

plurals
  1. POCreating a scrolling grid of different width cells
    primarykey
    data
    text
    <p>I am new to c# and WinPhone7 development and need a bit of guidance if someone could be so kind, so please excuse my ignorance.</p> <p>The issue I have is I need to create a Grid view for a TV Guide where you have a vertical list of channel logos on the left that scrolls up and down, and to its right we have a horizontally and vertically scrolling grid. Horizontal scrolling doesnt move the channel logos which is fixed on screen, but vertically scrolling grid also scrolls the logos as you would expect.</p> <p>Should I continue to attempt to do this using XAML and Silverlight or should I just do it via XNA?</p> <p>I ask because I have tried several different methods via Silverlight to get over to the two main problems I have:</p> <p><strong>Performance</strong></p> <p>As I receive the data from our API using ASync requests I create a background worker thread which parses the JSON and creates programme cells on the grid 'canvas' view using Dispatch.Invoke. As this happens there is no gradual feedback, the whole thing waits until everything is done and then suddenly the grid appears. I would like the cells to appear on a channel by channel basis or on a cell-by-cell basis without blocking the UI so scrolling still works nicely but this doesnt seem to happen.</p> <p>I am having issues as any sort of work using UIElements is done on the UI thread which on WinPhone7 is the main thread (I believe), this includes parsing XAML or creating/modiyfing UIElements even if they arent added to anything on-screen or visible. This means I cannot improve things by pre-creating or re-using elements.</p> <p>I have tried doing as much as possible in a worker thread and just the tiny bit of UI work being dispatched to the UI thread to minimise the blocking, and it doesnt seem to help.</p> <p><strong>Memory</strong></p> <p>Clearly I cannot create 'programme cells' for each tv programme event for potentially hundreds (we support more than 650 channels) for 7 days as the phone would run out of memory very quickly; so I would like to create a virtual grid where cells are created and loaded into the canvas view only for the viewport being currently seen.</p> <p>I have two problems with this:</p> <ol> <li>the UI blocking of doing any UI work stops any scrolling as above so creating new cells in the background that are to be scrolled into view cant happen without blocking the UI</li> <li>there are no scroll events being sent by the scroll view, I have experimented with binding to the scrollbars in the scrollview to get offset values but this doesnt work very well as it just updates in fits and starts so if you do lots of scrolling, nothing gets sent until there is a pause or OnIdle I guess.</li> </ol> <p>Is it me messing up and should I therefore persevere, or I am doing something that cant be done and I should try a different tact like doing it via XNA?</p> <p>Any advice would be greatly appreciated.</p> <p><strong>Edit: A bit more information and some sample code</strong></p> <p>I have a Programme class that contains things like start time and title, a Channel class that has name and logo etc but also an array of programmes.</p> <p>When I retrieve my API data, I create a channel object and add it to an array of channels, then I add the programmes to the channels Programmes array. Once all the programmes for a channel have been added to the array I post it to an ChannelProgrammesComplete event listener for the UI to be updated.</p> <pre><code>&lt;ScrollViewer ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollBarVisibility="Visible"&gt; &lt;Canvas x:Name="ProgGrid" Height="55" Width="393" VerticalAlignment="Top" HorizontalAlignment="Left"&gt; &lt;/Canvas&gt; &lt;/ScrollViewer&gt; public void ChannelProgrammesComplete( object sender, EventArgs e ) { var bw = new BackgroundWorker(); bw.WorkerReportsProgress = true; bw.DoWork += ( doWorkSender, args ) =&gt; { 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 &amp;&amp; left &lt; 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 &gt; 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 ); } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload