我有一个WPF图像控件,它的source属性绑定到一个返回图像的属性。
<Image Grid.Row="0"
Source="{Binding Path=ImageSrc, NotifyOnTargetUpdated=True, Converter={StaticResource imgToSrcConverter}}" />
然后我有一个转换器,它将图像绑定到source属性并将其转换为bitmapImage。当bitmapimage下载完成后,我想在我的视图模型中执行一个方法,所以我在BitmapImage中订阅了DownloadCompleted事件。那么如何从转换器中调用视图模型中的方法呢?它会违反MVVM原则吗?
转换器:
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();
bi.DownloadCompleted += new EventHandler(bi_DownloadCompleted);
return bi;
}
return null;
}
public object ConvertBack(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
private void bi_DownloadCompleted(object sender, EventArgs e)
{
// Call my method in view model
}
}
答案 0 :(得分:3)
您可以使用接受多个值的多转换器:
public class ImgToSrcConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
Image image = values[0] 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();
ViewModel vm = values[1] as ViewModel;
bi.DownloadCompleted += (s, e) =>
{
vm.Method();
};
return bi;
}
return null;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
<强>用法:强>
<Image Grid.Row="0">
<Image.Source>
<MultiBinding NotifyOnTargetUpdated="True" Converter="{StaticResource imgToSrcConverter}">
<Binding Path="ImageSrc" />
<Binding Path="." />
</MultiBinding>
</Image.Source>
</Image>
不,只要您的可测试应用程序逻辑保留在视图模型中,这就不会破坏MVVM模式。
答案 1 :(得分:1)
您可以做的是将DataContext
直接传递给转换器,然后从那里访问适用的属性/方法。
将图片xaml更新为:
<Image Grid.Row="0"
Source="{Binding Path=DataContext,
RelativeSource={RelativeSource Self},
NotifyOnTargetUpdated=True,
Converter={StaticResource imgToSrcConverter}}" />
然后,保持对ViewModel的引用,并相应地调用:
public class ImgToSrcConverter : IValueConverter
{
private MyViewModel _dataContext;
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
var dataContext = value as MyViewModel;
if (dataContext != null)
{
_dataContext = dataContext;
var image = dataContext.ImageSrc 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();
bi.DownloadCompleted += new EventHandler(bi_DownloadCompleted);
return bi;
}
}
return null;
}
public object ConvertBack(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
private void bi_DownloadCompleted(object sender, EventArgs e)
{
_dataContext?.MyMethod();
}
}
注意,我觉得这对于MVVM来说有点代码味道,通常情况下,您永远不会希望通过转换器访问ViewModel。对我来说,似乎有些逻辑可以在ViewModel本身内加载/维护,而不是依赖于转换器。
答案 2 :(得分:0)
Theres是一种使用IMultiValueConverter的方法,因此您可以将图像和datacontext(vievmodel)转换为转换器... WPF: MultiBinding and IMultiValueConverter
另一种方法可能是EventAggregator / MessageBus,然后向您的ViewModel发送消息......?尽管许多人认为MessageBus可以被视为反模式。 Roll Your Own Simple Message Bus / Event Aggregator