WPF& MVVM:在不破坏模式的情况下更新图像字段

时间:2011-02-12 16:07:51

标签: wpf image mvvm

我目前正在学习如何使用MVVM模式编写WPF应用程序。我正在编写一个小型的联系人管理器应用程序,因此我的应用程序显示一个绑定到我的视图模型的列表框,以及一组绑定到ListBox.SelectedItem的字段。其中一个领域是联系人的照片。

我想使用OpenFileDialog更改编辑部分中的照片,因此Listbox项目将会更新,就像所有其他字段一样。

我首先尝试更新Image控件的source属性,但是这样做,我失去了Binding ... 然后我在Button_Click上编写了一个处理程序来更新Contact.Photo属性(它的类型是byte []),它可以工作。但是,不是从“更新控件”绑定到视图模型,而是从VM到控件的绑定,就像数据来自数据库一样。

(在代码中,LoadPhoto返回一个byte [])

private void Button_Click(object sender, RoutedEventArgs e)
{
    OpenFileDialog OpenFileDialog = new OpenFileDialog();
    if (OpenFileDialog.ShowDialog() == true)
    {
        (listbox.SelectedItem as ContactManager.ViewModel.Contact).Photo = 
                LoadPhoto(OpenFileDialog.FileName);
    }
}

我想知道它是否不会破坏MVVM模式......我不确定在视图中可以做什么...这是更新Contact对象的正确方法吗?有没有人有更好的解决方案来解决这个问题?

1 个答案:

答案 0 :(得分:2)

查看将按钮绑定到Command Binding而不是click事件 您可以使用Google找到DelegateCommand的实现 接下来,您可以从ViewModel公开可以从XAML绑定到Image的ImageSource。

我已经包含了一些代码片段以帮助您入门。

一旦你了解了基础知识,看看MVVM框架,比如Cinch,你就会找到一种方法来处理使用Services Interfaces IOpenFileService.cs的OpenFileDialog而不违反MVVM模式。< / p>

这是XAML:

  <Button Content="Update Photo" Command="{Binding UpdatePictureCommand}"/>

  <Image Source="{Binding EmployeePicture}"
                   VerticalAlignment="Center" HorizontalAlignment="Center"
                   Stretch="Fill" />

这是ViewModel:

  public MainViewModel()
  {
     UpdatePictureCommand = new DelegateCommand<object>(OnUpdatePictureCommand, CanUpdatePictureCommand);
  }

  public ICommand UpdatePictureCommand { get; private set; }
  private void OnUpdatePictureCommand(object obj)
  {
    OpenFileDialog OpenFileDialog = new OpenFileDialog();
   if (OpenFileDialog.ShowDialog() == true)
   {
     //(listbox.SelectedItem as ContactManager.ViewModel.Contact).Photo = 
     //    LoadPhoto(OpenFileDialog.FileName);
     Stream reader = File.OpenRead(OpenFileDialog.FileName);
     System.Drawing.Image photo = System.Drawing.Image.FromStream((Stream)reader);

     MemoryStream finalStream = new MemoryStream();
     photo.Save(finalStream, ImageFormat.Png);

     // translate to image source
     PngBitmapDecoder decoder = new PngBitmapDecoder(finalStream, BitmapCreateOptions.PreservePixelFormat,
                                         BitmapCacheOption.Default);
     EmployeePicture =  decoder.Frames[0];;
  }

  private bool CanMoveFirstCommand(object obj)
  {
     return true;
  }

  private ImageSource _employeePicture;
  public ImageSource EmployeePicture
  {
     get
     {
        return _employeePicture;
     }
     set
     {
        _employeePicture = value;
        OnPropertyChanged("EmployeePicture");
     }
  }