我目前正在学习如何使用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");
}
}