c# - ¿Error de VirtualizingStackPanel y TextWrapping? Telefono windows
silverlight windows-phone-7 (4)
Tengo un comportamiento extraño con VirtualizingStackPanel
. Tengo una lista con elementos que contienen TextBlock
con TextWrap="Wrap"
. Aquí está el código:
<ListBox x:Name="messagesList" ItemsSource="{Binding Messages}" >
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
...
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
<CheckBox Style="{Binding Own, Converter={StaticResource MsgTypeToStyle}}"
Tag="{Binding TimeString}"
IsEnabled="True">
<TextBlock Text="{Binding Content}" TextWrapping="Wrap"/>
</CheckBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Funciona bastante bien, pero si trato de desplazarme muy rápido (usando el emulador del mouse, no de forma promisoria) hay algo de retraso en el desplazamiento, probablemente HorizontallOffset
algunas veces calcula incorrecto, y en la parte inferior termina con un resultado muy extraño (ver imagen, derecha la imagen demuestra un comportamiento normal).
Después de la investigación, descubrí ese problema en combinación VirtualizingStackPanel
y TextBlock.TextWrap="Wrap"
, si elimino un elemento de esta pareja, todo funciona correctamente.
Pero necesito virtualización debido a la gran cantidad de elementos, y TextWrap
para la correcta visualización del texto.
Así que pienso en hacer mi propia implementación de Virtualizing Panel, ¿pueden guiarme, cómo hacerlo o cómo solucionar el problema actual?
UPD: el problema:
en las dos primeras imágenes, ListBox
ya se desplazó (!) hacia abajo (ya no se puede desplazar hacia abajo), pero los elementos se colocaron incorrectamente y se corrigió la ubicación que se muestra en la imagen de la derecha. Esto sucede solo si se desplaza muy rápido.
UPD2: Gracias a Milan Aggarwal. Él proporcionó un buen caso de mi problema aquí . Parece que es realmente un error en ListBox
. La solución provista no se ajusta a mi escenario, porque necesito interactuar con los controles dentro del elemento ListBox
. Ahora estoy tratando de atrapar el evento ManipulationCompleted
y verifico si es Inertial
, si eso significa scroll y pongo el foco en la página:
void messagesList_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
{
if (e.IsInertial)
this.Focus();
}
PD gracias por deseos de buena suerte;)
¿Cuál es el problema en la 2da pantalla? ¿Te refieres a un gran espacio vacío después del último mensaje? ¿El último mensaje no está en la parte inferior de la página? ¿Estoy obteniendo esto bien?
En realidad, no intenté reproducir tu código y tu error, pero mi punto es que, dado que estás utilizando libs de terceros (Silverlight Toolkit) en tu aplicación, ¿por qué no utilizar también las herramientas de Coding4Fun ?
Escribí esta clase ficticia:
public class Message
{
public string Time { get; private set; }
public string Content { get; private set; }
public Message(string time, string content)
{
Time = time;
Content = content;
}
}
Luego puse este código falso en el constructor de la página principal:
var _messages = new ObservableCollection<Message>();
for (int i = 0; i < 50; i++)
{
_messages.Add(new Message("12:40", "Teh very long string which should be wrapped. Pavel Durov gives WP7 Contest winners less money than he did for Android/iOS winners. FFFUUUUUUUUUUUUUU "));
}
this.ListBox.ItemsSource = _messages;
Y en xaml pongo un cuadro de lista con control de burbuja de chat de toolkit:
<ListBox x:Name="ListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<c4fToolkit:ChatBubble>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"
Text="{Binding Content}"
TextWrapping="Wrap"/>
<TextBlock Grid.Row="1"
Text="{Binding Time}"
HorizontalAlignment="Right"/>
</Grid>
</c4fToolkit:ChatBubble>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Lo ejecuté y no vi comportamientos extraños, tal vez un poco rezagados. Hay el resultado:
Espero haber hecho algo de ayuda.
Удачи с конкурсом, я баспользовал, но не верю, что за 1,5 месяца удастся сделать приличный клиент.
¿Cuál es el problema en la segunda imagen? ¿Es que BlackArea apareció en absoluto, o es que ScrollView no "rebotó" después de que el desplazamiento terminó para llenar el área negra con contenido?
Es crucial saber esto, porque ... este efecto es simplemente natural para WPF / WP7 .. Por cierto. el desplazamiento debe "rebotar" después del desplazamiento en exceso, pero parece que tiene un error y a veces se olvida de hacerlo.
Lo estoy preguntando porque las áreas en blanco y negro a menudo no solo están en WP7, sino en cualquier lugar donde haya un ScrollViewer XAMLish con desplazamiento inercial. Verá, cuando se desplaza más rápido de lo que la plataforma puede proporcionar nuevos elementos, simplemente se desplaza fuera de los elementos precalculados y una vez que "sobre" desplaza muy lejos, los elementos de entrada lenta descubren abruptamente que no hay más elementos, por lo tanto - volver área vacía ..
Esto ocurre principalmente cuando algunas condiciones suceden a la vez: se desplaza rápidamente (yay), sus enlaces son lentos (expresiones excesivamente complicadas), la representación de la plantilla es lenta (plantillas de UI complejas no reutilizables), los enlaces no saben cuántos elementos hay (vinculados a IEnumerable
no IList
-> no .Count información!), o el procesador no sabe la altura que se debe reservar para un elemento (el elemento no es de altura constante, pero cada elemento debe calcularse para determinar su propio altura exacta).
Si quieres corregirlo, primero debes luchar contra esas causas o debes implementar tu propio desplazamiento o hackeo en el panel de pila de virtualización y sincronizar la alimentación de elementos de bindingsource con el desplazamiento para que el desplazamiento adivine mejor la altura total: por ejemplo , muestre solo un pequeño artículo a la vez, escuche los eventos de desplazamiento y agregue / elimine dinámicamente el siguiente paquete de elementos del encabezado / final de la lista. Esto resolverá el problema al no permitir que se desplace rápidamente :)))))
Creo que restringir la altura del artículo es la forma más fácil. ¿No puedes hacer algo inteligente para que los artículos sean de tamaño constante?
Para superar la aparición de negro en el desplazamiento, necesita virtualizar su control de desplazamiento. Para eso, debes heredar IList
y crear una Collection
propia similar a ObservableCollection
en la que tendrás que anular el indexador predeterminado en función de tus requisitos de almacenamiento en caché y al mismo tiempo mantener un caché para tus artículos. Siento que esto podría ser lo que estás buscando: http://blogs.msdn.com/b/ptorr/archive/2010/08/16/virtualizing-data-in-windows-phone-7-silverlight-applications.aspx
Hay un proyecto de muestra en esa página. Pruébalo.
También siento que estás enfrentando este problema http://blog.rsuter.com/?p=258 . Supongo que esto se resolverá usando la virtualización misma. Espero eso ayude
Sugiero que cree la función más simple posible que calcula una altura para el bloque de texto envuelto y se une a eso. De esta manera, obtendrá el beneficio de los elementos de altura variable en el cuadro de lista, pero siga usando el panel de pila de virtualización.