我正在尝试用一个月的时间来习惯 MVVM 和 WPF。我正在尝试做一些基本的事情,但我不断遇到问题。我感觉大部分问题都是通过网上搜索解决的。但现在命令出现了问题。
问:我看到他们正在使用 RelayCommand、DelegateCommand 或 SimpleCommand。像这样:
public ICommand DeleteCommand => new SimpleCommand(DeleteProject);
即使我像他们一样创建了所有内容,我仍然将 => new SimpleCommand(DeleteProject);
部分用红色下划线表示。
到目前为止,我正在通过为每个命令创建命令类来解决这个问题,但这感觉不是正确的方法。
- 问:我也会发布整个项目,我想知道我是否做错了什么或者需要改进哪些地方。
xaml:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="380" Width="250">
<StackPanel DataContext="{Binding Source={StaticResource gallery}}" Margin="10">
<ListView DataContext="{Binding Source={StaticResource viewModel}}"
SelectedItem="{Binding SelectedGallery}"
ItemsSource="{Binding GalleryList}"
Height="150">
<ListView.View>
<GridView>
<GridViewColumn Header="Name" Width="100" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Path" Width="100" DisplayMemberBinding="{Binding Path}"/>
</GridView>
</ListView.View>
</ListView>
<TextBlock Text="Name" Margin="0, 10, 0, 5"/>
<TextBox Text="{Binding Name}" />
<TextBlock Text="Path" Margin="0, 10, 0, 5" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<TextBox Text="{Binding Path}" Grid.Column="0"/>
<Button Command="{Binding Path=ShowFolderClick, Source={StaticResource viewModel}}"
CommandParameter="{Binding}"
Content="..." Grid.Column="1" Margin="10, 0, 0, 0"/>
</Grid>
<Grid Margin="0, 10, 0, 0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Command="{Binding Path=AddClick, Source={StaticResource viewModel}}"
CommandParameter="{Binding}" Content="Add" Grid.Column="0" Margin="15,0,0,0" />
<Button Command="{Binding Path=DeleteClick, Source={StaticResource viewModel}}"
Content="Delete" Grid.Column="2" Margin="0,0,15,0" />
</Grid>
</StackPanel>
型号:
class Gallery : INotifyPropertyChanged
{
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
OnPropertyChanged("Name");
}
}
private string _path;
public string Path
{
get
{
return _path;
}
set
{
_path = value;
OnPropertyChanged("Path");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(params string[] propertyNames)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
foreach (string propertyName in propertyNames) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
handler(this, new PropertyChangedEventArgs("HasError"));
}
}
}
模型 View :
class GalleryViewModel : INotifyPropertyChanged
{
public GalleryViewModel()
{
GalleryList = new ObservableCollection<Gallery>();
this.ShowFolderClick = new ShowFolderDialog(this);
this.AddClick = new AddGalleryCommand(this);
this.DeleteClick = new DeleteGalleryCommand(this);
}
private ObservableCollection<Gallery> _galleryList;
public ObservableCollection<Gallery> GalleryList
{
get { return _galleryList; }
set {
_galleryList = value;
OnPropertyChanged("GalleryList");
}
}
private Gallery _selectedGallery;
public Gallery SelectedGallery
{
get { return _selectedGallery; }
set {
_selectedGallery = value;
OnPropertyChanged("SelectedGallery");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(params string[] propertyNames)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
foreach (string propertyName in propertyNames) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
handler(this, new PropertyChangedEventArgs("HasError"));
}
}
public AddGalleryCommand AddClick { get; set; }
public void AddGalleryClick(Gallery gallery)
{
Gallery g = new Gallery();
g.Name = gallery.Name;
g.Path = gallery.Path;
GalleryList.Add(g);
}
public DeleteGalleryCommand DeleteClick { get; set; }
public void DeleteGalleryClick()
{
if (SelectedGallery != null)
{
GalleryList.Remove(SelectedGallery);
}
}
public ShowFolderDialog ShowFolderClick { get; set; }
public void ShowFolderDialogClick(Gallery gallery)
{
System.Windows.Forms.FolderBrowserDialog browser = new System.Windows.Forms.FolderBrowserDialog();
string tempPath = "";
if (browser.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
tempPath = browser.SelectedPath; // prints path
}
gallery.Path = tempPath;
}
}
命令:
class AddGalleryCommand : ICommand
{
public GalleryViewModel _viewModel { get; set; }
public AddGalleryCommand(GalleryViewModel ViewModel)
{
this._viewModel = ViewModel;
}
public bool CanExecute(object parameter)
{
/*if (parameter == null)
return false;*/
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
this._viewModel.AddGalleryClick(parameter as Gallery);
}
}
class DeleteGalleryCommand : ICommand
{
public GalleryViewModel _viewModel { get; set; }
public DeleteGalleryCommand(GalleryViewModel ViewModel)
{
this._viewModel = ViewModel;
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
this._viewModel.DeleteGalleryClick();
}
}
class ShowFolderDialog : ICommand
{
public GalleryViewModel _viewModel { get; set; }
public ShowFolderDialog(GalleryViewModel ViewModel)
{
this._viewModel = ViewModel;
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
this._viewModel.ShowFolderDialogClick(parameter as Gallery);
}
}
感谢您到目前为止的阅读,我会感激我得到的每一个建议。
最佳答案
有一些框架/库可以帮助简化命令绑定(bind)。例如,MVVMLight 具有 RelayCommand 的通用实现,只需要您创建属性并为其执行分配方法名称。
Here这是如何使用 Mvvmlight Relaycommand 的示例。
关于c# - MVVM,我是否必须将每个命令保留在自己的类中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47501743/