WPF和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对象的正确方法吗?有没有人有更好的解决方案来解决这个问题?

最佳答案 查看将按钮绑定到Command Binding而不是click事件.

您可以使用Google找到DelegateCommand的实现.

接下来,您可以从ViewModel公开可以从XAML绑定到Image的ImageSource.

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

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

这是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");
     }
  }
点赞