【问题标题】:WPF & MVVM : Update an image field without breaking the patternWPF 和 MVVM :在不破坏模式的情况下更新图像字段
【发布时间】:2011-06-26 03:05:02
【问题描述】:

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

我想使用 OpenFileDialog 更改编辑部分中的照片,以便更新列表框项,就像所有其他字段一样。

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

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

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 模式...我不确定在视图中可以做什么...这是更新联系人对象的正确方法吗?有没有人有更好的解决这个问题的方法?

【问题讨论】:

    标签: wpf image mvvm


    【解决方案1】:

    考虑将您的按钮绑定到命令绑定而不是单击事件。
    您可以使用 Google 找到 DelegateCommand 的实现。
    接下来,您可以从 ViewModel 公开一个 ImageSource,您可以从 XAML 绑定到您的 Image。

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

    一旦您了解了基础知识,请查看 MVVM 框架,例如 Cinch,您会找到一种使用 Services InterfacesIOpenFileService.cs 来处理 OpenFileDialog 的方法,不会违反 MVVM 模式。

    这是 XAML:

      <Button Content="Update Photo" Command="{Binding UpdatePictureCommand}"/>
    
      <Image Source="{Binding EmployeePicture}"
                       VerticalAlignment="Center" HorizontalAlignment="Center"
                       Stretch="Fill" />
    

    这是视图模型:

      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");
         }
      }
    

    【讨论】:

    • 我已经尝试使用带有命令参数(要更新的对象)的命令,我的代码看起来像你的。但我对这种方式也有同样的疑惑:VM 中的 OpenFileDialog 不是打破这种模式吗?我会试试 Cinch 看看如何用它来处理这个问题。
    • 我为 Cinch 添加了几个链接。有两个版本,一个用于 VS 2008,一个用于 VS 2010。
    • 感谢您的帮助!我看了看 Cinch,实际上,它解决了我的问题。我将看一下框架本身以自己实现它,作为我“培训”的一个步骤;-)
    猜你喜欢
    • 2019-06-27
    • 2014-08-22
    • 1970-01-01
    • 2011-12-04
    • 2019-10-16
    • 2011-03-11
    • 1970-01-01
    • 2018-03-08
    • 1970-01-01
    相关资源
    最近更新 更多