I noticed this strange behavior yesterday when putting together a demo application for WP. Usually I never pass in plain items, and never the ‘same’- but this time I did. When bound to an observablecollection of type int or string, if the value is the same, the control will add first one item, then two, then three, then four. Instead of adding one each time. Basically it does this:
Items.Count ++
If I however change the item, say string, to something unique (a GUID.ToString for example) it has the expected behavior.
This is regardless of how the DataContext is set, or if I add LayoutMode="List" IsGroupingEnabled="False" to the control.
Why does it do this? And is this expected behavior?
I spent hours searching for an answer, so please don’t just paste random links about the control :)
Code for the view:
<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 behind:
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());
}
}
}
This is a bug in LongListSelector. The reason it works with Guid is because this'll do a reference comparison and avoid the bug.
Here's a workaround by using a reference object instead:
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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With