如果列表中有多个图像,我需要在x个时间后在鼠标悬停时更改图像。
为了实现这一点,我开发了一个自定义图像控件,我的控件基本上有两个属性MainImageSource,它是一个BitmapImage和ImageUrl,它是一个IList。
现在我在这里做的是onmouseenter启动一个计时器并在计时器hass过去并重置图像onmouseleave事件后将MainImageSource
更改为列表中的下一个图像(如果有的话)。
一切正常,就像我设置图像时一样,按照预期设置图像。
现在我需要在ListBox中使用这个控件,它是数据绑定到类型为FileItem
的ObservableCollection(自定义类)。现在在列表框中我需要设置该数组,所以我所做的是,在FileItem
中添加一个名为Imageurls
的属性string[]
。
在xaml中,我使用以下内容进行数据绑定。
<local:MBImage ImageUrl="{Binding ImageUrls}" Source="{Binding MainImageSource}" />
但MBImage
的ImageUrl从未设置过。
所以现在有两件事
ImageUrls
FileItem
ImageUrl
MBImage
Source="{Binding MainImageSource}"
。MBImage
。因为它在Source
内部使用。如果我不使用MainImageSource属性,即使我更新了MBImage 'ImageUrls' property not found on 'object' ''MBImage' (Name='')'
,它也不会改变图像。添加到一切是有更好的方法来实现我的主要目标,即在悬停时显示多个图像。如果我找到比这更好的方法并且使用更多WPF的优势,我愿意重写所有内容。
被修改
这是错误
class MBImage : Image, INotifyPropertyChanged
{
private List<BitmapImage> bmpImages = new List<BitmapImage>();
private Timer imgChangeTimer = new Timer(1000);
private int curImage = 0;
BitmapImage _MainImageSource = null;
public event PropertyChangedEventHandler PropertyChanged;
public static readonly DependencyProperty ImageUrlProperty = DependencyProperty.Register("ImageUrl", typeof(IList<string>), typeof(MBImage));
public IList<string> ImageUrl
{
get { return (IList<string>)this.GetValue(ImageUrlProperty); }
set
{
this.SetValue(ImageUrlProperty, value);
DownloadImages();
}
}
public MBImage()
{
imgChangeTimer.Elapsed += new ElapsedEventHandler(imgChangeElapsed);
DataContext = this;
}
public BitmapImage MainImageSource
{
get
{
return _MainImageSource;
}
set
{
_MainImageSource = value;
OnPropertyChanged("MainImageSource");
}
}
private void DownloadImages()
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (s, e) =>
{
List<ImageDownloadArgs> argList = new List<ImageDownloadArgs>();
int index = (int)e.Argument;
int count = 1;
if (index == -1)
{
count = ImageUrl.Count();
index = 1;
}
for (int i = index; i < count; i++)
{
ImageDownloadArgs args = new ImageDownloadArgs();
args.Index = i;
Uri uri = new Uri(ImageUrl[i], UriKind.Absolute);
using (WebClient webClient = new WebClient())
{
webClient.Proxy = null;
webClient.CachePolicy = new RequestCachePolicy(RequestCacheLevel.Default);
try
{
byte[] imageBytes = null;
imageBytes = webClient.DownloadData(uri);
if (imageBytes == null)
{
e.Result = null;
return;
}
MemoryStream imageStream = new MemoryStream(imageBytes);
args.Img = new BitmapImage();
args.Img.BeginInit();
args.Img.StreamSource = imageStream;
args.Img.CacheOption = BitmapCacheOption.OnLoad;
args.Img.EndInit();
args.Img.Freeze();
imageStream.Close();
argList.Add(args);
}
catch (WebException)
{
//argList.Add(args);
}
}
}
e.Result = argList;
};
worker.RunWorkerCompleted += (s, e) =>
{
List<ImageDownloadArgs> argList = e.Result as List<ImageDownloadArgs>;
bool shouldDownloadRest = false;
foreach (ImageDownloadArgs args in argList)
{
if (args != null)
{
if (args.Index == 0)
{
MainImageSource = args.Img;
bmpImages.Add(args.Img);
shouldDownloadRest = true;
}
else
{
bmpImages.Add(args.Img);
}
}
}
worker.Dispose();
if (shouldDownloadRest)
worker.RunWorkerAsync(-1);
};
worker.RunWorkerAsync(0);
}
private void imgChangeElapsed(object sender, ElapsedEventArgs e)
{
Console.WriteLine("Time out");
MainImageSource = bmpImages[++curImage % bmpImages.Count()];
}
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
protected override void OnMouseEnter(System.Windows.Input.MouseEventArgs e)
{
imgChangeTimer.Start();
}
protected override void OnMouseLeave(System.Windows.Input.MouseEventArgs e)
{
imgChangeTimer.Stop();
MainImageSource = bmpImages[0];
curImage = 0;
}
}
显示它在MBImage中寻找ImageUrls而不是ObservableCollection类型的listbox itemsource。
MBImage.cs
{{1}}
答案 0 :(得分:1)
问题是你的构造函数Setting the DataContext of MBImage to itself
中DataContext = this;
,你不应该这样做。这就是你在ImageUrl="{Binding ImageUrls}"
删除DataContext = this;
此行,因为它不是必需的。
另外我看到你在属性设置器中做了一些工作,这不会从Xaml绑定调用,因为wpf内部调用GetValue和SetValue函数..如果你想对属性值集进行一些注册,请注册ValueChanged在定义它时在依赖项属性元数据中回调,并在valuechanged处理程序
中执行此操作public static readonly DependencyProperty ImageUrlProperty = DependencyProperty.Register("ImageUrl", typeof(IList<string>), typeof(MBImage), new FrameworkPropertyMetadata(null, ImageUrlsChanged));