2012-01-13 48 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