2017-10-17 124 views
1

我有一個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 
    } 
} 
+0

如果您的應用有重要的'BitmapImage',那麼視圖模型中的'ImageSrc'屬性應該是'BitmapImage'類型,並且您不需要轉換器 – ASh

+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模式您的可測試應用程序邏輯保留在視圖模型中。

+0

使用您的解決方案,當視圖模型中的屬性「ImageSrc」發生改變時,轉換器已到達,但現在事件DownloadCompleted從未被觸發。爲什麼?也許是因爲一旦bi返回,bi對象就被破壞了? – user1624552

+0

我在示例代碼中將事件處理程序定義爲匿名方法。除此之外,我沒有改變任何東西。你有沒有在匿名方法中設置斷點?如果事件在之前被提出,它仍然會被提升。 – mm8

+0

是的,我在vm.Method()中放置了一個斷點。在匿名的DownloadCompleted事件中。轉換器方法被執行,但事件從未被引發。 – user1624552

1

你可以做的是通過直接的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本身中加載/維護,而不依賴於轉換器。

+0

使用這個,轉換器沒有被調用。 – user1624552

+0

@ user1624552您在綁定可訪問的位置使用'imgToSrcConverter'鍵創建了轉換器的資源? –

+0

@BradleyUffner是的,我在Window.Resources部分窗口的開頭創建了它。在窗口資源的下面,所有的內容都在一個主要的網格中,我把datacontext關聯到如下:。也許這是影響,這是爲什麼不轉換轉換器的原因? – user1624552

相關問題