如果列表中存在多个图像,我需要在 x 时间后更改鼠标悬停时的图像。
为了实现这一点,我开发了一个自定义图像控件,我的控件有两个属性,基本上 MainImageSource 是一个 BitmapImage 和 ImageUrl 这是一个 IList。
现在我在这里做的是 onmouseenter 启动一个计时器并MainImageSource
在计时器结束并重置图像 onmouseleave 事件后更改到列表中的下一个图像(如果有的话)。
一切正常,就像我设置图像网址时它按预期设置图像一样。
现在我需要在 ListBox 中使用这个控件,它是数据绑定到 ObservableCollection 类型FileItem
(自定义类)的数据。现在在列表框中,我需要设置该数组,所以我所做的是,在FileItem
调用Imageurls
类型中添加一个属性string[]
。在 xaml 中,我使用以下内容进行数据绑定。
<local:MBImage ImageUrl="{Binding ImageUrls}" Source="{Binding MainImageSource}" />
MBImage
但从未设置过ImageUrl 。
所以现在有两件事
- 我怎样才能与
ImageUrls
of绑定。FileItem
ImageUrl
MBImage
- 我怎样才能摆脱
Source="{Binding MainImageSource}"
。因为它在内部使用MBImage
。如果我不使用 MainImageSource 属性,即使我更新了 MBImage 也不会更改图像Source
。
除了一切之外,还有更好的方法来实现我的主要目标,即在悬停时显示多个图像。如果我找到比这更好的方法并且使用更多 WPF 的优势,我愿意重写所有内容。
已编辑
这是错误
'ImageUrls' property not found on 'object' ''MBImage' (Name='')'
这表明它在 MBImage 中寻找 ImageUrls 而不是 ObservableCollection 类型的列表框 itemsource。
MBImage.cs
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;
}
}