MVVM WPF Fire图像加载完成后的命令(加载事件)
我在我的视图中有一个WPF图像控件。当图像被加载时,我想要触发一个在我的模型视图中定义和执行的事件。我怎样才能做到这一点?我不知道如何使用命令执行此操作。MVVM WPF Fire图像加载完成后的命令(加载事件)
<Image Grid.Row="0"
Source="{Binding Path=ImageSrc, NotifyOnTargetUpdated=True, Converter={StaticResource imgToSrcConverter}}"
Visibility="{Binding ImgVisibility}"
RenderTransformOrigin="0,0"
SnapsToDevicePixels="True"
OverridesDefaultStyle="False"
TargetUpdated="targetUpdated"
Cursor="Hand"
RenderOptions.BitmapScalingMode="LowQuality"
RenderOptions.EdgeMode="Aliased">
<Image.Effect>
<DropShadowEffect Opacity="0.8" BlurRadius="8">
</DropShadowEffect>
</Image.Effect>
</Image>
转换:
public class ImgToSrcConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
Image image = value as Image;
if (image != null)
{
MemoryStream ms = new MemoryStream();
image.Save(ms, image.RawFormat);
ms.Seek(0, SeekOrigin.Begin);
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = ms;
bi.EndInit();
return bi;
}
return null;
}
public object ConvertBack(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
视图模型:
public Image ImageSrc
{
get
{
MemoryStream ms = new MemoryStream(GetImageAsByteArray());
Image img = Image.FromStream(ms);
// Here I call method to hide splash screen "Loading"
return img;
}
}
您可以在后台加载图像,并称之为 “NotifyPropertyChanged” 的形象已经被加载时:
private static Image SplashScreenImage = GetSplashScreenImage();
private Image ActualImage = null;
private bool IsLoading = false;
public Image ImageSrc
{
get
{
if (ActualImage != null)
return ActualImage;
if (!IsLoading)
{
IsLoading = true;
// start loading image in background
Task.Run(() =>
{
MemoryStream ms = new MemoryStream(GetImageAsByteArray());
ActualImage = Image.FromStream(ms);
}).ContinueWith(t => PropertyChanged("ImageSrc"), TaskScheduler.FromCurrentSynchronizationContext());
}
return SplashScreenImage;
}
}
我正在使用NET 3.5 SP1,没有可用的任务。 – user1624552
你也可以使用线程代替;) – JanDotNet
这不完全是我想要的。我也不明白你为什么要将启动画面图像返回到图像源。我假装做的是:当我做了很长时间的任务时,我显示一个启动屏幕显示“正在加载...”。这一长期任务包括将图像从高分辨率转换为低分辨率。这就是GetImageAsByteArray。然后,一旦我将图像转换为低分辨率,我想关闭启动画面。我遇到的问题是,一旦调用了OnPropertyChanged(“ImageSrc”)并且启动画面关闭后,图像花费几秒钟时间可见..... – user1624552
您可以使用异步无需转换器绑定:
<Image Source="{Binding ImageSrc, IsAsync=True}"/>
的ImageSrc属性的getter直接创建一个BitmapFrame或BitmapImage的是这样的:
public ImageSource ImageSrc
{
get
{
ImageSource image;
using (var stream = new MemoryStream(GetImageAsByteArray()))
{
image = BitmapFrame.Create(
stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
SplashScreenEnabled = false;
return image;
}
}
public bool SplashScreenEnabled { get; set; } // firing PropertyChanged omitted
如果你想调用指令时, Loaded
事件为Image
元素触发,您可以使用交互触发器:
<Image Grid.Row="0"
Source="{Binding Path=ImageSrc, NotifyOnTargetUpdated=True, Converter={StaticResource imgToSrcConverter}}"
Visibility="{Binding ImgVisibility}"
RenderTransformOrigin="0,0"
SnapsToDevicePixels="True"
OverridesDefaultStyle="False"
TargetUpdated="targetUpdated"
Cursor="Hand"
RenderOptions.BitmapScalingMode="LowQuality"
RenderOptions.EdgeMode="Aliased"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding YourCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Image.Effect>
<DropShadowEffect Opacity="0.8" BlurRadius="8">
</DropShadowEffect>
</Image.Effect>
</Image>
有关如何通过执行视图模型命令来处理事件的更多信息,请参阅以下博文:https://blog.magnusmontin.net/2013/06/30/handling-events-in-an-mvvm-wpf-application/。
另一种选择可能是简单地从源setter方法执行命令:
public Image ImageSrc
{
get
{
MemoryStream ms = new MemoryStream(GetImageAsByteArray());
Image img = Image.FromStream(ms);
YourCommandProperty.Execute(null);
return img;
}
}
你它的源属性绑定到您的视图模型的属性?然后,您可以简单地在调用视图模型属性getter时执行操作。 – Clemens
什么是“模型视图”?这些条款准确无误。 –
@Clemens - 设置属性和完成加载不是一回事。 –