WPF MVVM:从转换器调用视图模型中的方法
我有一个WPF图像控件,它的源属性绑定到返回图像的属性。WPF MVVM:从转换器调用视图模型中的方法
<Image Grid.Row="0"
Source="{Binding Path=ImageSrc, NotifyOnTargetUpdated=True, Converter={StaticResource imgToSrcConverter}}" />
然后,我有一个转换器,将图像绑定到源属性并将其转换为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
}
}
你可以使用多转换器,接受几个值:
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模式您的可测试应用程序逻辑保留在视图模型中。
使用您的解决方案,当视图模型中的属性“ImageSrc”发生改变时,转换器已到达,但现在事件DownloadCompleted从未被触发。为什么?也许是因为一旦bi返回,bi对象就被破坏了? – user1624552
我在示例代码中将事件处理程序定义为匿名方法。除此之外,我没有改变任何东西。你有没有在匿名方法中设置断点?如果事件在之前被提出,它仍然会被提升。 – mm8
是的,我在vm.Method()中放置了一个断点。在匿名的DownloadCompleted事件中。转换器方法被执行,但事件从未被引发。 – user1624552
你可以做的是通过直接的DataContext
到转换器,然后从那里访问适用属性/方法。
更新图像XAML到:
<Image Grid.Row="0"
Source="{Binding Path=DataContext,
RelativeSource={RelativeSource Self},
NotifyOnTargetUpdated=True,
Converter={StaticResource imgToSrcConverter}}" />
然后,握住你的视图模型的引用,并据此称:
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本身中加载/维护,而不依赖于转换器。
使用这个,转换器没有被调用。 – user1624552
@ user1624552您在绑定可访问的位置使用'imgToSrcConverter'键创建了转换器的资源? –
@BradleyUffner是的,我在Window.Resources部分窗口的开头创建了它。在窗口资源的下面,所有的内容都在一个主要的网格中,我把datacontext关联到如下:
使用IMultiValueConverter即使世界的方法,所以你可以得到你的形象和DataContext的(vievmodel)的转换器... WPF: MultiBinding and IMultiValueConverter
另一种方式可能是一个EventAggregator/MessageBus,然后将消息发送到您的视图模型。 ..?尽管许多人会认为MessageBus可以被视为反模式。 Roll Your Own Simple Message Bus/Event Aggregator
如果您的应用有重要的'BitmapImage',那么视图模型中的'ImageSrc'属性应该是'BitmapImage'类型,并且您不需要转换器 – ASh
我不确定我是否理解您的'重新尝试实现?你能否详细说明你想要做什么? “下载”是什么意思?当这个“下载”完成时你会做什么? –