2014-03-25 5 views
5

Ich habe dieses merkwürdige Verhalten gestern bemerkt, als ich eine Demo-Anwendung für WP zusammenstellte. Gewöhnlich übergebe ich niemals einfache Dinge und niemals das gleiche - aber dieses Mal habe ich es getan. Wenn das Steuerelement an eine ObservableCollection vom Typ int oder string gebunden ist, fügt das Steuerelement zuerst ein Element, dann zwei, dann drei und dann vier hinzu, wenn der Wert derselbe ist. Anstatt jedes Mal ein neues hinzuzufügen. Im Grunde ist es tut dies:Warum fügt der LongListSelector zusätzliche Elemente hinzu, wenn die Sammlungswerte identisch sind?

Items.Count ++

Wenn ich aber das Element ändern, sagen Zeichenfolge, um etwas Einzigartiges (a GUID.ToString zum Beispiel) ist es das erwartete Verhalten hat.

Dies ist unabhängig davon, wie der DataContext festgelegt ist, oder wenn ich LayoutMode = "List" IsGroupingEnabled = "False" zum Steuerelement hinzufügen.

Warum macht es das? Und ist das erwartete Verhalten?

Ich verbrachte Stunden auf eine Antwort zu suchen, so einfach nicht wahllos Links über die Steuer einfügen :)

-Code für die Ansicht bitte:

<phone:PhoneApplicationPage 
x:Class="Bug.MainPage" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" 
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
mc:Ignorable="d" 
FontFamily="{StaticResource PhoneFontFamilyNormal}" 
FontSize="{StaticResource PhoneFontSizeNormal}" 
Foreground="{StaticResource PhoneForegroundBrush}" 
SupportedOrientations="Portrait" Orientation="Portrait" 
shell:SystemTray.IsVisible="True" 
DataContext="{Binding RelativeSource={RelativeSource Self}}"> 

<StackPanel> 
    <Button Click="Button_Click">Add</Button> 
    <phone:LongListSelector Width="300" Height="600" ItemsSource="{Binding Items}"/> 
</StackPanel> 
</phone:PhoneApplicationPage> 

-Code hinter:

using System.Collections.ObjectModel; 
using System.Windows; 


namespace Bug 
{ 
    public partial class MainPage 
    { 
     // Constructor 
     public MainPage() 
     { 
      InitializeComponent(); 

      Items = new ObservableCollection<string>(); 

      //DataContext = this; 
     } 

     public ObservableCollection<string> Items { get; set; } 

     private void Button_Click(object sender, RoutedEventArgs e) 
     { 
      Items.Add("A"); 

      // This works as expected 
      //Items.Add(Guid.NewGuid().ToString()); 
     } 
    } 

} 
+0

So Items.Add wird nur einmal jedes Mal getroffen, aber die Sammlung geht von 1, 3, 6, 10, etc.? – invalidusername

+1

Ich habe auch [dieses Problem] (http://stackoverflow.com/questions/19356668/long-list-selector-observable-collection-and-visual-tree-problems), und leider habe ich keine Lösung gefunden bis jetzt. Wenn Sie Grouping in LLS nicht verwenden, verwenden Sie ListBox - ohne dieses Problem. – Romasz

+0

ivalidusername: nein es fügt items.count plus eins hinzu. Probieren Sie den Code aus. @Romasz die Dokumente sagen, dass die LLS aus Leistungsgründen über LB empfohlen wird. AFAIK –

Antwort

2

Dies ist ein Fehler in LongListSelector. Der Grund, warum es mit Guid funktioniert, ist, dass es einen Referenzvergleich durchführt und den Fehler vermeidet.

Hier ist eine Abhilfe, indem stattdessen ein Referenzobjekt mit:

public partial class MainPage : PhoneApplicationPage 
{ 
    // Constructor 
    public MainPage() 
    { 
     InitializeComponent(); 

     // Sample code to localize the ApplicationBar 
     Items = new ObservableCollection<Object>(); 

    } 
    public ObservableCollection<Object> Items { get; set; } 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     Items.Add(new Object() { Value = "A" }); 

     // This works as expected 
     //Items.Add(Guid.NewGuid().ToString()); 
    } 

} 
public class Object 
{ 
    public string Value { get; set; } 

    public override string ToString() 
    { 
     return Value; 
    } 
} 
+0

Laurent hat mir geholfen, den Fehler an das WP-Team zu übermitteln, aber ich denke, dass wir bei so vielen, die dies versuchen, bestätigen können, dass es ein Bug ist. Ich wählte dies als Antwort, da es eine Lösung bietet (ich weiß, dass es nicht die Frage war - aber viele könnten zu dem Q kommen, der nach einer Lösung sucht). Danke, wie immer :) –

+0

Keine Sorge. Übrigens, ich wollte nicht "Referenzvergleich" sagen, ich meinte, dass der Wert, den du jedesmal hinzufügst, anders ist. Das Problem tritt auch bei zum Beispiel 'int' auf. Fügen Sie dieselbe Nummer immer wieder hinzu und Sie sehen das gleiche Verhalten. Fügen Sie eine andere Nummer hinzu, und Sie nicht. – dotMorten

+0

Yup, das ist mir aufgefallen. Ich würde gerne wissen, was es tatsächlich tut, wenn es die Elemente hinzufügt. –

-1

Ich bin mir ziemlich sicher, dass es ein Bug von LongListSelector ist.

Ich denke, wenn es Diff zwischen Daten lädt, nimmt es alle Erscheinung von "A" in Sammlung in Liste.

Lassen Sie uns für WP8.1 warten, wahrscheinlich LongListSelector wird :-)

VJ veraltet

0

Dies ist keine Antwort bedeutet, aber ich geändert @ ursprünglichen Code des IrisClasson ein bisschen das Problem mehr markieren . Wenn Sie zwischen dem Hinzufügen eines Elements "A" und eines Elements "B" wechseln, zeigt die Liste ein merkwürdiges Verhalten, wenn Sie eines der Elemente zweimal nacheinander hinzufügen, korrigiert sich jedoch selbst, wenn Sie das andere Element hinzufügen. Ich habe eine ListBox hinzugefügt, die an dieselben Daten gebunden ist, damit Sie sehen können, wie die Liste aussehen soll.

Ausblick:

<phone:PhoneApplicationPage 
    x:Class="Bug.MainPage" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" 
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d" 
    FontFamily="{StaticResource PhoneFontFamilyNormal}" 
    FontSize="{StaticResource PhoneFontSizeNormal}" 
    Foreground="{StaticResource PhoneForegroundBrush}" 
    SupportedOrientations="Portrait" Orientation="Portrait" 
    shell:SystemTray.IsVisible="True" 
    DataContext="{Binding RelativeSource={RelativeSource Self}}"> 

    <StackPanel> 
     <StackPanel Orientation="Horizontal"> 
      <Button Click="Button_Click">Add A</Button> 
      <Button Click="Button_Click1">Add B</Button> 
      <Button Click="Button_Click2">Clear</Button> 
     </StackPanel> 
     <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"> 
     <phone:LongListSelector x:Name="MyLongList" Width="200" Height="600" 
           ItemsSource="{Binding Items}"/> 
     <ListBox x:Name="MyListBox" Width="200" Height="600" 
       ItemsSource="{Binding Items}" /> 
    </StackPanel> 
    </StackPanel> 
</phone:PhoneApplicationPage> 

Codebehind:

using System.Collections.ObjectModel; 
using System.Diagnostics; 
using System.Windows; 
using Microsoft.Phone.Controls; 

namespace Bug 
{ 
    public partial class MainPage : PhoneApplicationPage 
    { 
     // Constructor 
     public MainPage() 
     { 
      InitializeComponent(); 

      Items = new ObservableCollection<string>(); 

      Items.CollectionChanged += Items_CollectionChanged; 
     } 

     void Items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
     { 
      Debug.WriteLine("CollectionChanged"); 
     } 

     public ObservableCollection<string> Items { get; private set; } 

     private void Button_Click(object sender, RoutedEventArgs e) 
     { 
      Items.Add("A"); 

      // This works as expected 
      //Items.Add(Guid.NewGuid().ToString()); 
     } 

     private void Button_Click1(object sender, RoutedEventArgs e) 
     { 
      Items.Add("B"); 

      // This works as expected 
      //Items.Add(Guid.NewGuid().ToString()); 
     } 

     private void Button_Click2(object sender, RoutedEventArgs e) 
     { 
      Items.Clear(); 
     } 
    } 
} 
+1

Vielen Dank für die zusätzlichen Informationen! I upvoted –

0

Ich denke, es irgendwie zu Two different "strings" are the same object instance? verwendet ist, so genannten String http://en.wikipedia.org/wiki/String_interning Internierung, was bedeutet, dass es nicht, wie viele „A“ string egal Sie werden es erstellen wird immer noch auf den gleichen Speicher zeigen.

Zum Beispiel: wenn Sie versuchen, "Guid.NewGuid(). ToString())" in ein privates Feld zu speichern und diese Instanz für "Items.Add (Obj)" verwenden, wird das gleiche Problem führen.

Auch die Anzahl für Items ist korrekt, also muss es ein Fehler in LLS sein und die Art und Weise, wie same-instance-Objekte gerendert werden.

Verwandte Themen