虚拟化不改变新的可见项目的属性 [英] Virtualisation not changing properties of new visible items

查看:129
本文介绍了虚拟化不改变新的可见项目的属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前使用的自定义图像对象(约℃的包装; 对象;图片>)在ListView。我的自定义图像对象的属性,当一个新的列表视图项是可见不改变(实现)。

I am currently using a custom Image object(a wrapper around <Image> object) in a listView. The properties of my custom Image object don't change when a new listview item is visible(realised).

举例来说,如果我的列表视图(含30项不同的图片网址和不同的文本)有3个项目上的第一个滚动,然后第10项具有相同的图像作为第一个项目。这些图像的顺序重复[1-9] [1-9] [1-9] ......但令我惊讶的文本是所有30 listViewItems不同。

For instance if my listview (containing 30 items with different image urls and different text) has 3 items on the first scroll then the 10th item has the same image as the 1st item. The images repeat in the order [1-9][1-9][1-9].... But to my surprise the text is different in all 30 listViewItems.

在调试,我发现我的图像对象setter方法被称为只在第9个项目。 ?有人可以阐明如何其他系统组件的光(系统映像/ TextBlock的工作的罚款)获得新的元素值

On debugging I found that the setter for my image object gets called only for the first 9 items. Can somebody shed light on how other system components(System Image/TextBlock working fine) get new element values?

相关类属性的代码片段:

Code snippet of relevant class property:

public sealed partial class CustomImage : UserControl
{

public static readonly DependencyProperty ImageSourceStringProperty = DependencyProperty.Register("ImageSourceString", typeof(string), typeof(CustomImage), new PropertyMetadata(null, new PropertyChangedCallback(ImageSourceStringChanged)));
    public string ImageSourceString
    {
        get { return (string)GetValue(ImageSourceStringProperty); }
        set
        {
            //THIS NEVER GETS HIT FOR ITEMS AFTER 9th ITEM
            SetValue(ImageSourceStringProperty, value);
            //{More code here}
        }
    }
}

Xaml Usage
<ListView ItemsSource="{Binding}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <custom:customImage x:Name="Img" ImageSourceString="{Binding ImgPath}"/>
                    <TextBlock Grid.Column="1" Text="{Binding Name}"/>
                 </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>



我缺少的是如何工作的?如果事情是不明确,请让我知道,我可以澄清一下。

Am I missing how it is supposed to work? In case something is not clear please let me know, I can clarify.

推荐答案

的getter 二传手依赖项属性不能保证运行,我们最好不要放任何其他代码二传手。请注意下面的注意在的 相对=nofollow>自定义依赖属性

The getter and setter of a dependency property are not guaranteed to be run, we'd better not put any other code in setter. Please note following Caution in Custom dependency properties:

在所有,但特殊情况下,您的包装实现应该只执行了的GetValue和的SetValue操作。否则,当你的财产是通过XAML设置当它通过代码设置与你会得到不同的行为。为了提高效率,XAML分析器设置依赖属性时跳过的封装。只要有可能,它使用依赖属性的注册表。

In all but exceptional circumstances, your wrapper implementations should perform only the GetValue and SetValue operations. Otherwise, you'll get different behavior when your property is set via XAML versus when it is set via code. For efficiency, the XAML parser bypasses wrappers when setting dependency properties; whenever possible, it uses the registry of dependency properties.

因此,而不是在二传手你的财产,我们可以使用 ImageSourceStringChanged 方法行事像下面的新值:

So instead of reacting in the setter of your property, we can use ImageSourceStringChanged method to act on the new value like following:

private static void ImageSourceStringChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
    CustomImage currentImage = obj as CustomImage;
    string oldValue = e.OldValue as string;
    string newValue = e.NewValue as string;
    MainPage.logMsg("ImageSource = " + newValue);
    if (oldValue == null || !oldValue.Equals(newValue))
    {
        string path = newValue;
        if (string.IsNullOrEmpty(path))
        {
            Uri imageFileUri = new Uri("ms-appx:///Assets/Images/failed.png");
            currentImage.mainImage.ImageSource = new BitmapImage(imageFileUri);
        }
        else
        {
            Uri imageFileUri = null;
            try
            {
                imageFileUri = new Uri(path);
            }
            catch
            {
                imageFileUri = new Uri("ms-appx:///Assets/Images/failed.png");
            }
            if (imageFileUri != null)
            {
                currentImage.mainImage.ImageSource = new BitmapImage(imageFileUri);
            }
        }
    }
}



另外,因为你的的DependencyProperty 字符串,你并不需要比较的OldValue的类型的NewValue ,如同值更改回调只是调用。见的属性改变行为结构和枚举的。

Besides, since the type of your DependencyProperty is string, you do not need to compare the OldValue and NewValue as the callback is only invoked if the value changed. See Property changed behavior for structures and enumerations.

如果一个的DependencyProperty 是一个枚举或结构时,可能会被调用,即使内部值的结构或枚举值没有变化。这是从系统不同的原始诸如其中,如果该值变仅调用字符串。

If the type of a DependencyProperty is an enumeration or a structure, the may be invoked even if the internal values of the structure or the enumeration value did not change. This is different from a system primitive such as a string where it only is invoked if the value changed.

所以 CustomImage 的完整代码可能会喜欢:

So the complete code of CustomImage may like:

public sealed partial class CustomImage : UserControl
{
    public static readonly DependencyProperty ImageSourceStringProperty = DependencyProperty.Register("ImageSourceString", typeof(string), typeof(CustomImage), new PropertyMetadata(null, new PropertyChangedCallback(ImageSourceStringChanged)));

    public string ImageSourceString
    {
        get { return (string)GetValue(ImageSourceStringProperty); }
        set
        {
            SetValue(ImageSourceStringProperty, value);
        }
    }

    private static void ImageSourceStringChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        CustomImage currentImage = obj as CustomImage;
        string path = e.NewValue as string;
        MainPage.logMsg("ImageSource = " + path);

        if (string.IsNullOrEmpty(path))
        {
            Uri imageFileUri = new Uri("ms-appx:///Assets/Images/failed.png");
            currentImage.mainImage.ImageSource = new BitmapImage(imageFileUri);
        }
        else
        {
            Uri imageFileUri = null;
            try
            {
                imageFileUri = new Uri(path);
            }
            catch
            {
                imageFileUri = new Uri("ms-appx:///Assets/Images/failed.png");
            }
            if (imageFileUri != null)
            {
                currentImage.mainImage.ImageSource = new BitmapImage(imageFileUri);
            }
        }
    }

    public CustomImage()
    {
        this.InitializeComponent();
    }
}

这篇关于虚拟化不改变新的可见项目的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆