c# - MVVM,我是否必须将每个命令保留在自己的类中?

标签 c# wpf mvvm viewmodel

我正在尝试用一个月的时间来习惯 MVVM 和 WPF。我正在尝试做一些基本的事情,但我不断遇到问题。我感觉大部分问题都是通过网上搜索解决的。但现在命令出现了问题。

  1. 问:我看到他们正在使用 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/

    相关文章:

    c# - 从 javascript 调用 c# 函数不起作用

    c# - List<> 与 IEnumerable<>,在定义新类或新 View 模型类时

    c# - WPF套接字客户端结构

    c# - XAML 在 Visual Studio 中不刷新

    unit-testing - 为什么我的 ViewModel 不应该依赖于服务的具体实现?

    c# - MVVM UI 使用 WPF 控制用户依赖的可见性

    c# - 如何取消 IEnumerable?

    c# - 具有最小长度的 JSON 模式,除非为空/空

    WPF DatePicker 文本框白色边框不可编辑

    WPF 和 MVVM : best architecture for Time-consuming search results?