简体   繁体   中英

wp7 listbox element tap 'sender' object uniqueness

Has appeared a strange situation with listboxitem inner sender (i just think that this sender is to blame, but not sure...)

There is ItemTemplate for ListBox:

<ListBox x:Name="list">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel x:Name="stack_panel">
                    <Image Source="{Binding ImageSource}" Tap="Image_Tap"></Image>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
</ListBox>

Every item in ListBox has a some image with tap event:

private void Image_Tap(object sender, GestureEventArgs e)
{
   Image i = (Image)sender;
   i.Source = new BitmapImage(new Uri("Images/yellow.png", UriKind.RelativeOrAbsolute));
}

Also, there is a class for easy images changing:

public class listItems
{
    public string ImageSource { get; set; }
}

Right. Now i ready to add some elements in listbox:

for (int i = 0; i < 100;i++)
   list.Items.Add(new listItems
   {
       ImageSource = "Images/black.png"
   });

So, let's click on zeroth sun image:

图片1

Everything is ok! Let's continue, and click on a second picture:

图片2

Right, the sun is shining..but.. stop, what is that? 0_o

在此处输入图片说明

I didn't click on this item, but image of this has changed! That happens with not only th item, also it has been with some other random items (53, 81, ...)

What do you think about this? Can sender has reference to many elements?

What do you think about this?

By default list box control reuses visual items to optimize the performance. You can switch it off if you want, however for your 100 items the performance will drop of course.

There's better solution. Instead of what you're doing, you should store the selection state somewhere in your model, not just in a visual tree.

Your item class could be:

public class listItems: INotifyPropertyChanged
{
    bool _selected = false;
    public bool isSelected
    {
        get { return _selected; }
        set 
        {
            if( value == _selected )
                return;
            _selected = value;
            var pc = this.PropertyChanged;
            if( null != pc )
                pc( this, new PropertyChangedEventArgs( "ImageSource" ) );
        }
    }

    public string ImageSource { get { return _selected ? "Images/yellow.png" : "Images/black.png"; } }

    public event PropertyChangedEventHandler PropertyChanged;
}

INotifyPropertyChanged interface allows the visual tree to be notified about the property changes.

And here's the tap handler:

void Image_Tap( object sender, GestureEventArgs e )
{
    Image img = (Image)sender;
    listItems item = (listItems)img.DataContext;
    item.isSelected = true;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM