我目前在listView中使用自定义Image对象(<Image>
对象的包装器)。当新的列表视图项可见(已实现)时,我的自定义Image对象的属性不会更改。
例如,如果我的列表视图(包含30个具有不同图像网址和不同文本的项目)在第一个滚动条目上有3个项目,则第10个项目与第一个项目具有相同的图像。图像按[1-9] [1-9] [1-9]的顺序重复......但令我惊讶的是,所有30个listViewItem中的文本都不同。
在调试时,我发现只为前9个项目调用了我的图像对象的setter。有人可以了解其他系统组件(系统映像/ TextBlock正常工作)如何获得新的元素值?
相关类属性的代码段:
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>
我错过了它应该如何工作?如果有什么不清楚请告诉我,我可以澄清。
答案 0 :(得分:3)
不保证依赖属性的getter
和setter
可以运行,我们最好不要在setter
中放置任何其他代码。请注意Custom dependency properties中的警告:
除了特殊情况外,您的包装器实现应该只执行GetValue和SetValue操作。否则,当您通过XAML设置属性时,通过代码设置属性时,您将获得不同的行为。为了提高效率,XAML解析器在设置依赖项属性时会绕过包装器;只要有可能,它就会使用依赖属性的注册表。
因此,我们可以使用setter
方法对新值进行操作,而不是对您的属性ImageSourceStringChanged
做出反应,而不是如下所示:
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
的类型为string
,因此您无需比较OldValue
和NewValue
,因为仅在值更改时才会调用回调。请参阅Property changed behavior for structures and enumerations。
如果 DependencyProperty 的类型是枚举或结构,即使结构的内部值或枚举值没有改变,也可以调用它。这与系统原语(如字符串)不同,只有在值更改时才会调用它。
所以CustomImage
的完整代码可能会像:
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();
}
}