Я новичок в разработке C# и WinPhone7, и вам нужно немного руководства, если кто-то может быть таким добрым, поэтому, пожалуйста, извините мое невежество.Создание сетки с прокруткой разной ширины ячейки
У меня есть вопрос: мне нужно создать сетку для ТВ-гида, где у вас есть вертикальный список логотипов каналов слева, который прокручивается вверх и вниз, а справа - горизонтальная и вертикальная сетка прокрутки , Горизонтальная прокрутка не перемещает логотипы каналов, которые фиксируются на экране, но вертикальная прокрутка сетки также прокручивает логотипы, как и следовало ожидать.
Должен ли я продолжать попытки сделать это с помощью XAML и Silverlight или мне просто нужно это сделать с помощью XNA?
Я спрашиваю, потому что я попробовал несколько различных методов через Silverlight, чтобы получить к двум основным проблемам у меня есть:
Performance
Как я получаю данные из нашего API используется асинхронные запросами я создаю фоновый рабочий поток, который анализирует JSON и создает ячейки программы на экране «холст» сетки с помощью Dispatch.Invoke. Так как это происходит, нет постепенной обратной связи, все это ждет, пока все не будет сделано, а затем вдруг появится сетка. Я хотел бы, чтобы ячейки отображались на канале по каналам или на основе поэтапно, без блокировки пользовательского интерфейса, поэтому прокрутка по-прежнему работает хорошо, но это, похоже, не происходит.
У меня возникли проблемы, так как любая работа с использованием UIElements выполняется в потоке пользовательского интерфейса, который на WinPhone7 является основным потоком (я считаю), это включает в себя анализ XAML или создание/модификацию UIElements, даже если они не добавлены ни к чему на - экран или видимый. Это означает, что я не могу улучшить ситуацию путем создания или повторного использования элементов.
Я попытался сделать как можно больше в рабочем потоке и только крошечный бит работы пользовательского интерфейса, отправляемый в поток пользовательского интерфейса, чтобы свести к минимуму блокировку, и, похоже, это не помогает.
память
Очевидно, я не могу создать «программу клетки» для каждого события телепрограммы потенциально сотни (мы поддерживаем более 650 каналов) в течение 7 дней, как телефон будет бежать из памяти очень быстро; поэтому я хотел бы создать виртуальную сетку, где ячейки создаются и загружаются в представление холста только для просмотра в настоящее время.
У меня есть две проблем с этим:
- блокировка UI делать любую работу интерфейса останавливает любую прокрутку, как выше, так что создание новых клеток в фоновом режиме, которые будут прокручиваться в поле зрения не может произойти без блокировки пользовательского интерфейса
- событий прокрутки не отправляются прокруткой, я экспериментировал с привязкой к полосам прокрутки в 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);
}
Этот ответ неудобен, особенно если вы не предоставили нам проблемный код. Несмотря на это, похоже, что вы сможете сделать это без XNA, если вы избавитесь от этой уродливой вещи (подсказка: название начинается с буквы C), что полностью разрушит вашу производительность, как только вы сделаете что-нибудь более сложный с ним, чем отображение статических элементов в верхнем левом углу;) – Nuffin
Загрузка данных, когда пользователь прокручивает список до конца списка: http://danielvaughan.orpius.com/post/Scroll-Based-Data-Loading- in-Windows-Phone-7.aspx – Ku6opr
@Tobias Я добавил немного кода сейчас; этот образец удаляет все стековые панели, которые я использовал (это единственный способ создать вертикальную панель прокрутки канала и отдельную панель сетки, которая прокручивается как по горизонтали, так и по вертикали), абсолютно никакой разницы в скорости не произошло. Если я просматриваю, пока данные обрабатываются, он всплывает и останавливается, а затем внезапно появляется вся сетка ... нет постепенного рендеринга и не происходит гладкого UI – Dan