2012-01-13 3 views
0

Я новичок в разработке C# и WinPhone7, и вам нужно немного руководства, если кто-то может быть таким добрым, поэтому, пожалуйста, извините мое невежество.Создание сетки с прокруткой разной ширины ячейки

У меня есть вопрос: мне нужно создать сетку для ТВ-гида, где у вас есть вертикальный список логотипов каналов слева, который прокручивается вверх и вниз, а справа - горизонтальная и вертикальная сетка прокрутки , Горизонтальная прокрутка не перемещает логотипы каналов, которые фиксируются на экране, но вертикальная прокрутка сетки также прокручивает логотипы, как и следовало ожидать.

Должен ли я продолжать попытки сделать это с помощью XAML и Silverlight или мне просто нужно это сделать с помощью XNA?

Я спрашиваю, потому что я попробовал несколько различных методов через Silverlight, чтобы получить к двум основным проблемам у меня есть:

Performance

Как я получаю данные из нашего API используется асинхронные запросами я создаю фоновый рабочий поток, который анализирует JSON и создает ячейки программы на экране «холст» сетки с помощью Dispatch.Invoke. Так как это происходит, нет постепенной обратной связи, все это ждет, пока все не будет сделано, а затем вдруг появится сетка. Я хотел бы, чтобы ячейки отображались на канале по каналам или на основе поэтапно, без блокировки пользовательского интерфейса, поэтому прокрутка по-прежнему работает хорошо, но это, похоже, не происходит.

У меня возникли проблемы, так как любая работа с использованием UIElements выполняется в потоке пользовательского интерфейса, который на WinPhone7 является основным потоком (я считаю), это включает в себя анализ XAML или создание/модификацию UIElements, даже если они не добавлены ни к чему на - экран или видимый. Это означает, что я не могу улучшить ситуацию путем создания или повторного использования элементов.

Я попытался сделать как можно больше в рабочем потоке и только крошечный бит работы пользовательского интерфейса, отправляемый в поток пользовательского интерфейса, чтобы свести к минимуму блокировку, и, похоже, это не помогает.

память

Очевидно, я не могу создать «программу клетки» для каждого события телепрограммы потенциально сотни (мы поддерживаем более 650 каналов) в течение 7 дней, как телефон будет бежать из памяти очень быстро; поэтому я хотел бы создать виртуальную сетку, где ячейки создаются и загружаются в представление холста только для просмотра в настоящее время.

У меня есть две проблем с этим:

  1. блокировка UI делать любую работу интерфейса останавливает любую прокрутку, как выше, так что создание новых клеток в фоновом режиме, которые будут прокручиваться в поле зрения не может произойти без блокировки пользовательского интерфейса
  2. событий прокрутки не отправляются прокруткой, я экспериментировал с привязкой к полосам прокрутки в scrollview для получения значений смещения, но это не очень хорошо работает, поскольку оно просто обновляется в соответствии и запускается, поэтому, если вы делаете много прокрутка, ничего не отправляется до тех пор, пока не произойдет пауза или OnIdle.

Это ли я возиться, и поэтому я должен упорствовать, или я делаю то, что не может быть сделано, и я должен попробовать другой такт, как делать это через XNA?

Любые советы были бы весьма полезными.

Edit: немного больше информации и некоторые примеры кода

У меня есть класс программ, который содержит такие вещи, как время начала и название, класс канала, который имеет имя и логотип и т.д., но также множество программ.

Когда я извлекаю данные API, я создаю объект канала и добавляю его в массив каналов, а затем добавляю программы в канал. Как только все программы для канала были добавлены в массив, я отправляю его в прослушиватель событий ChannelProgrammesComplete для обновления интерфейса.

<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

Этот ответ неудобен, особенно если вы не предоставили нам проблемный код. Несмотря на это, похоже, что вы сможете сделать это без XNA, если вы избавитесь от этой уродливой вещи (подсказка: название начинается с буквы C), что полностью разрушит вашу производительность, как только вы сделаете что-нибудь более сложный с ним, чем отображение статических элементов в верхнем левом углу;) – Nuffin

+0

Загрузка данных, когда пользователь прокручивает список до конца списка: http://danielvaughan.orpius.com/post/Scroll-Based-Data-Loading- in-Windows-Phone-7.aspx – Ku6opr

+0

@Tobias Я добавил немного кода сейчас; этот образец удаляет все стековые панели, которые я использовал (это единственный способ создать вертикальную панель прокрутки канала и отдельную панель сетки, которая прокручивается как по горизонтали, так и по вертикали), абсолютно никакой разницы в скорости не произошло. Если я просматриваю, пока данные обрабатываются, он всплывает и останавливается, а затем внезапно появляется вся сетка ... нет постепенного рендеринга и не происходит гладкого UI – Dan

ответ

1

Прежде всего, с помощью большого Canvas должно быть только последним средством - в большинстве случаев сочетания Grid или StackPanel (иногда в других StackPanel с) и предметов с Margin будет намного быстрее (они будут немного сложнее в обработке).

Чтобы сохранить приложение отзывчивым вы могли

  1. только загружать небольшие порции данных сразу (как, например, две страницы. Это позволит значительно уменьшить объем данных, оказываемые одновременно). Затем вы можете загрузить следующий фрагмент либо сразу, либо когда пользователь прокручивается в конце списка.
  2. Ускорьте обработку результатов. Если вы подождали 100 мс после вставки каждого элемента (или через 1 секунду после каждого канала, если вы хотите, чтобы канал был загружен сразу), влияние на отзывчивость должно быть почти упущено, а также тоже большое влияние на время загрузки. Указанные времена - это только оценки, если они слишком большие/маленькие, не стесняйтесь настраивать их в соответствии с вашими потребностями, чтобы обеспечить плавный пользовательский интерфейс.
+0

Спасибо. Мне было дано понять, что укладка нагрузок элементов на самом деле будет худшей по производительности, поэтому было сообщено, что холст будет лучше. Использование сетки элементов, уложенных вверх, было бы сложно сделать, потому что рисовать ячейку для программы 7pm на нескольких строках будет сложно выстроить, если в ней есть много программ, но не одна (я сначала попробовал это и много проблем так пошло на холст, поскольку это было намного точнее при позиционировании). Я постараюсь отложить обработку; снова я попробовал это с одной из моих других попыток, но попробую еще раз. – Dan

+0

Добавление небольшого Thread.Sleep сработало и дало ui некоторое свободное время для обновления вещей. Надеюсь, я получу больше событий с элементами прокрутки, чтобы я мог виртуализировать их. Благодарю. – Dan

Смежные вопросы