C# 创建抽象视图模型wpf
我正在尝试创建一个抽象ViewModel类,以及几个ViewModel类,它们将继承抽象ViewModel并实现它 到目前为止,我使用的是C# 创建抽象视图模型wpf,c#,wpf,inheritance,viewmodel,relaycommand,C#,Wpf,Inheritance,Viewmodel,Relaycommand,我正在尝试创建一个抽象ViewModel类,以及几个ViewModel类,它们将继承抽象ViewModel并实现它 到目前为止,我使用的是RelayCommand,它没有编译 这样的事能做吗 我正在添加我的代码: RelayCommand类: public class RelayCommand : ICommand { private readonly Action<object> m_executeAction; private readonly Predicate
RelayCommand
,它没有编译
这样的事能做吗
我正在添加我的代码:
RelayCommand类:
public class RelayCommand : ICommand
{
private readonly Action<object> m_executeAction;
private readonly Predicate<object> m_canExecute;
public RelayCommand(Action<object> executeAction) : this(executeAction, null) { }
public RelayCommand(Action<object> executeAction, Predicate<object> canExecute)
{
if (executeAction == null)
throw new ArgumentNullException("executeAction");
m_executeAction = executeAction;
m_canExecute = canExecute;
}
public bool CanExecute(object canExecuteParameter)
{
return (m_canExecute == null || m_canExecute(canExecuteParameter));
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object canExecuteParameter)
{
m_executeAction(canExecuteParameter);
}
}
public abstract class ViewModelBase : INotifyPropertyChanged, IDisposable
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged == null) return;
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnDispose() {}
public void Dispose()
{
OnDispose();
}
}
public class MainWindowViewModel : ViewModelBase
{
private IViewModel m_testViewModel;
private bool m_isFirstPlugin = true;
public MainWindowViewModel()
{
TestViewModel = new FirstViewModel();
}
public IViewModel TestViewModel
{
get { return m_testViewModel; }
set
{
m_testViewModel = value;
OnPropertyChanged("NewViewModel");
}
}
private ICommand m_changeCommand;
public ICommand ChangeCommand
{
get { return m_changeCommand ?? (m_changeCommand = new RelayCommand(Change)); }
set { m_changeCommand = value; }
}
private void Change(object parameter)
{
TestViewModel.Dispose();
TestViewModel = null;
if (m_isFirstPlugin)
TestViewModel = new SecondViewModel();
else
TestViewModel = new FirstViewModel();
m_isFirstPlugin = !m_isFirstPlugin;
}
}
public class IViewModel : ViewModelBase
{
private ICommand m_testCommand;
public ICommand TestCommand
{
get { return m_testCommand ?? (m_testCommand = new RelayCommand(Test)); }
set { m_testCommand = value; }
}
protected virtual void Test(object parameter) { }
}
public class FirstViewModel : IViewModel
{
protected override void Test(object parameter)
{
MessageBox.Show("On First Plugin.");
}
}
public class SecondViewModel : IViewModel
{
protected override void Test(object parameter)
{
MessageBox.Show("On Second Plugin.");
}
}
<Window x:Class="MvvmInheritence.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Testing" Height="100" Width="180"
xmlns:Local="clr-namespace:MvvmInheritence" WindowStartupLocation="CenterScreen" Background="Transparent">
<Window.DataContext>
<Local:MainWindowViewModel />
</Window.DataContext>
<Grid x:Name="MainGrid">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Button x:Name="TestButton" Content="Test!" Foreground="DarkRed" Background="LightBlue" Height="25" Width="100" Command="{Binding TestCommand, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DataContext="{Binding TestViewModel, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Row="0"/>
<Button x:Name="ChangeButton" Content="Change Plugin" Foreground="DarkRed" Background="LightBlue" Height="25" Width="100" Command="{Binding ChangeCommand, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1"/>
</Grid>
</Window>
主视图模型类:
public class RelayCommand : ICommand
{
private readonly Action<object> m_executeAction;
private readonly Predicate<object> m_canExecute;
public RelayCommand(Action<object> executeAction) : this(executeAction, null) { }
public RelayCommand(Action<object> executeAction, Predicate<object> canExecute)
{
if (executeAction == null)
throw new ArgumentNullException("executeAction");
m_executeAction = executeAction;
m_canExecute = canExecute;
}
public bool CanExecute(object canExecuteParameter)
{
return (m_canExecute == null || m_canExecute(canExecuteParameter));
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object canExecuteParameter)
{
m_executeAction(canExecuteParameter);
}
}
public abstract class ViewModelBase : INotifyPropertyChanged, IDisposable
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged == null) return;
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnDispose() {}
public void Dispose()
{
OnDispose();
}
}
public class MainWindowViewModel : ViewModelBase
{
private IViewModel m_testViewModel;
private bool m_isFirstPlugin = true;
public MainWindowViewModel()
{
TestViewModel = new FirstViewModel();
}
public IViewModel TestViewModel
{
get { return m_testViewModel; }
set
{
m_testViewModel = value;
OnPropertyChanged("NewViewModel");
}
}
private ICommand m_changeCommand;
public ICommand ChangeCommand
{
get { return m_changeCommand ?? (m_changeCommand = new RelayCommand(Change)); }
set { m_changeCommand = value; }
}
private void Change(object parameter)
{
TestViewModel.Dispose();
TestViewModel = null;
if (m_isFirstPlugin)
TestViewModel = new SecondViewModel();
else
TestViewModel = new FirstViewModel();
m_isFirstPlugin = !m_isFirstPlugin;
}
}
public class IViewModel : ViewModelBase
{
private ICommand m_testCommand;
public ICommand TestCommand
{
get { return m_testCommand ?? (m_testCommand = new RelayCommand(Test)); }
set { m_testCommand = value; }
}
protected virtual void Test(object parameter) { }
}
public class FirstViewModel : IViewModel
{
protected override void Test(object parameter)
{
MessageBox.Show("On First Plugin.");
}
}
public class SecondViewModel : IViewModel
{
protected override void Test(object parameter)
{
MessageBox.Show("On Second Plugin.");
}
}
<Window x:Class="MvvmInheritence.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Testing" Height="100" Width="180"
xmlns:Local="clr-namespace:MvvmInheritence" WindowStartupLocation="CenterScreen" Background="Transparent">
<Window.DataContext>
<Local:MainWindowViewModel />
</Window.DataContext>
<Grid x:Name="MainGrid">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Button x:Name="TestButton" Content="Test!" Foreground="DarkRed" Background="LightBlue" Height="25" Width="100" Command="{Binding TestCommand, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DataContext="{Binding TestViewModel, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Row="0"/>
<Button x:Name="ChangeButton" Content="Change Plugin" Foreground="DarkRed" Background="LightBlue" Height="25" Width="100" Command="{Binding ChangeCommand, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1"/>
</Grid>
</Window>
IViewModel类:
public class RelayCommand : ICommand
{
private readonly Action<object> m_executeAction;
private readonly Predicate<object> m_canExecute;
public RelayCommand(Action<object> executeAction) : this(executeAction, null) { }
public RelayCommand(Action<object> executeAction, Predicate<object> canExecute)
{
if (executeAction == null)
throw new ArgumentNullException("executeAction");
m_executeAction = executeAction;
m_canExecute = canExecute;
}
public bool CanExecute(object canExecuteParameter)
{
return (m_canExecute == null || m_canExecute(canExecuteParameter));
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object canExecuteParameter)
{
m_executeAction(canExecuteParameter);
}
}
public abstract class ViewModelBase : INotifyPropertyChanged, IDisposable
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged == null) return;
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnDispose() {}
public void Dispose()
{
OnDispose();
}
}
public class MainWindowViewModel : ViewModelBase
{
private IViewModel m_testViewModel;
private bool m_isFirstPlugin = true;
public MainWindowViewModel()
{
TestViewModel = new FirstViewModel();
}
public IViewModel TestViewModel
{
get { return m_testViewModel; }
set
{
m_testViewModel = value;
OnPropertyChanged("NewViewModel");
}
}
private ICommand m_changeCommand;
public ICommand ChangeCommand
{
get { return m_changeCommand ?? (m_changeCommand = new RelayCommand(Change)); }
set { m_changeCommand = value; }
}
private void Change(object parameter)
{
TestViewModel.Dispose();
TestViewModel = null;
if (m_isFirstPlugin)
TestViewModel = new SecondViewModel();
else
TestViewModel = new FirstViewModel();
m_isFirstPlugin = !m_isFirstPlugin;
}
}
public class IViewModel : ViewModelBase
{
private ICommand m_testCommand;
public ICommand TestCommand
{
get { return m_testCommand ?? (m_testCommand = new RelayCommand(Test)); }
set { m_testCommand = value; }
}
protected virtual void Test(object parameter) { }
}
public class FirstViewModel : IViewModel
{
protected override void Test(object parameter)
{
MessageBox.Show("On First Plugin.");
}
}
public class SecondViewModel : IViewModel
{
protected override void Test(object parameter)
{
MessageBox.Show("On Second Plugin.");
}
}
<Window x:Class="MvvmInheritence.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Testing" Height="100" Width="180"
xmlns:Local="clr-namespace:MvvmInheritence" WindowStartupLocation="CenterScreen" Background="Transparent">
<Window.DataContext>
<Local:MainWindowViewModel />
</Window.DataContext>
<Grid x:Name="MainGrid">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Button x:Name="TestButton" Content="Test!" Foreground="DarkRed" Background="LightBlue" Height="25" Width="100" Command="{Binding TestCommand, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DataContext="{Binding TestViewModel, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Row="0"/>
<Button x:Name="ChangeButton" Content="Change Plugin" Foreground="DarkRed" Background="LightBlue" Height="25" Width="100" Command="{Binding ChangeCommand, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1"/>
</Grid>
</Window>
FirstViewModel类:
public class RelayCommand : ICommand
{
private readonly Action<object> m_executeAction;
private readonly Predicate<object> m_canExecute;
public RelayCommand(Action<object> executeAction) : this(executeAction, null) { }
public RelayCommand(Action<object> executeAction, Predicate<object> canExecute)
{
if (executeAction == null)
throw new ArgumentNullException("executeAction");
m_executeAction = executeAction;
m_canExecute = canExecute;
}
public bool CanExecute(object canExecuteParameter)
{
return (m_canExecute == null || m_canExecute(canExecuteParameter));
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object canExecuteParameter)
{
m_executeAction(canExecuteParameter);
}
}
public abstract class ViewModelBase : INotifyPropertyChanged, IDisposable
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged == null) return;
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnDispose() {}
public void Dispose()
{
OnDispose();
}
}
public class MainWindowViewModel : ViewModelBase
{
private IViewModel m_testViewModel;
private bool m_isFirstPlugin = true;
public MainWindowViewModel()
{
TestViewModel = new FirstViewModel();
}
public IViewModel TestViewModel
{
get { return m_testViewModel; }
set
{
m_testViewModel = value;
OnPropertyChanged("NewViewModel");
}
}
private ICommand m_changeCommand;
public ICommand ChangeCommand
{
get { return m_changeCommand ?? (m_changeCommand = new RelayCommand(Change)); }
set { m_changeCommand = value; }
}
private void Change(object parameter)
{
TestViewModel.Dispose();
TestViewModel = null;
if (m_isFirstPlugin)
TestViewModel = new SecondViewModel();
else
TestViewModel = new FirstViewModel();
m_isFirstPlugin = !m_isFirstPlugin;
}
}
public class IViewModel : ViewModelBase
{
private ICommand m_testCommand;
public ICommand TestCommand
{
get { return m_testCommand ?? (m_testCommand = new RelayCommand(Test)); }
set { m_testCommand = value; }
}
protected virtual void Test(object parameter) { }
}
public class FirstViewModel : IViewModel
{
protected override void Test(object parameter)
{
MessageBox.Show("On First Plugin.");
}
}
public class SecondViewModel : IViewModel
{
protected override void Test(object parameter)
{
MessageBox.Show("On Second Plugin.");
}
}
<Window x:Class="MvvmInheritence.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Testing" Height="100" Width="180"
xmlns:Local="clr-namespace:MvvmInheritence" WindowStartupLocation="CenterScreen" Background="Transparent">
<Window.DataContext>
<Local:MainWindowViewModel />
</Window.DataContext>
<Grid x:Name="MainGrid">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Button x:Name="TestButton" Content="Test!" Foreground="DarkRed" Background="LightBlue" Height="25" Width="100" Command="{Binding TestCommand, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DataContext="{Binding TestViewModel, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Row="0"/>
<Button x:Name="ChangeButton" Content="Change Plugin" Foreground="DarkRed" Background="LightBlue" Height="25" Width="100" Command="{Binding ChangeCommand, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1"/>
</Grid>
</Window>
SecondViewModel类:
public class RelayCommand : ICommand
{
private readonly Action<object> m_executeAction;
private readonly Predicate<object> m_canExecute;
public RelayCommand(Action<object> executeAction) : this(executeAction, null) { }
public RelayCommand(Action<object> executeAction, Predicate<object> canExecute)
{
if (executeAction == null)
throw new ArgumentNullException("executeAction");
m_executeAction = executeAction;
m_canExecute = canExecute;
}
public bool CanExecute(object canExecuteParameter)
{
return (m_canExecute == null || m_canExecute(canExecuteParameter));
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object canExecuteParameter)
{
m_executeAction(canExecuteParameter);
}
}
public abstract class ViewModelBase : INotifyPropertyChanged, IDisposable
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged == null) return;
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnDispose() {}
public void Dispose()
{
OnDispose();
}
}
public class MainWindowViewModel : ViewModelBase
{
private IViewModel m_testViewModel;
private bool m_isFirstPlugin = true;
public MainWindowViewModel()
{
TestViewModel = new FirstViewModel();
}
public IViewModel TestViewModel
{
get { return m_testViewModel; }
set
{
m_testViewModel = value;
OnPropertyChanged("NewViewModel");
}
}
private ICommand m_changeCommand;
public ICommand ChangeCommand
{
get { return m_changeCommand ?? (m_changeCommand = new RelayCommand(Change)); }
set { m_changeCommand = value; }
}
private void Change(object parameter)
{
TestViewModel.Dispose();
TestViewModel = null;
if (m_isFirstPlugin)
TestViewModel = new SecondViewModel();
else
TestViewModel = new FirstViewModel();
m_isFirstPlugin = !m_isFirstPlugin;
}
}
public class IViewModel : ViewModelBase
{
private ICommand m_testCommand;
public ICommand TestCommand
{
get { return m_testCommand ?? (m_testCommand = new RelayCommand(Test)); }
set { m_testCommand = value; }
}
protected virtual void Test(object parameter) { }
}
public class FirstViewModel : IViewModel
{
protected override void Test(object parameter)
{
MessageBox.Show("On First Plugin.");
}
}
public class SecondViewModel : IViewModel
{
protected override void Test(object parameter)
{
MessageBox.Show("On Second Plugin.");
}
}
<Window x:Class="MvvmInheritence.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Testing" Height="100" Width="180"
xmlns:Local="clr-namespace:MvvmInheritence" WindowStartupLocation="CenterScreen" Background="Transparent">
<Window.DataContext>
<Local:MainWindowViewModel />
</Window.DataContext>
<Grid x:Name="MainGrid">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Button x:Name="TestButton" Content="Test!" Foreground="DarkRed" Background="LightBlue" Height="25" Width="100" Command="{Binding TestCommand, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DataContext="{Binding TestViewModel, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Row="0"/>
<Button x:Name="ChangeButton" Content="Change Plugin" Foreground="DarkRed" Background="LightBlue" Height="25" Width="100" Command="{Binding ChangeCommand, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1"/>
</Grid>
</Window>
Xaml:
public class RelayCommand : ICommand
{
private readonly Action<object> m_executeAction;
private readonly Predicate<object> m_canExecute;
public RelayCommand(Action<object> executeAction) : this(executeAction, null) { }
public RelayCommand(Action<object> executeAction, Predicate<object> canExecute)
{
if (executeAction == null)
throw new ArgumentNullException("executeAction");
m_executeAction = executeAction;
m_canExecute = canExecute;
}
public bool CanExecute(object canExecuteParameter)
{
return (m_canExecute == null || m_canExecute(canExecuteParameter));
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object canExecuteParameter)
{
m_executeAction(canExecuteParameter);
}
}
public abstract class ViewModelBase : INotifyPropertyChanged, IDisposable
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged == null) return;
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnDispose() {}
public void Dispose()
{
OnDispose();
}
}
public class MainWindowViewModel : ViewModelBase
{
private IViewModel m_testViewModel;
private bool m_isFirstPlugin = true;
public MainWindowViewModel()
{
TestViewModel = new FirstViewModel();
}
public IViewModel TestViewModel
{
get { return m_testViewModel; }
set
{
m_testViewModel = value;
OnPropertyChanged("NewViewModel");
}
}
private ICommand m_changeCommand;
public ICommand ChangeCommand
{
get { return m_changeCommand ?? (m_changeCommand = new RelayCommand(Change)); }
set { m_changeCommand = value; }
}
private void Change(object parameter)
{
TestViewModel.Dispose();
TestViewModel = null;
if (m_isFirstPlugin)
TestViewModel = new SecondViewModel();
else
TestViewModel = new FirstViewModel();
m_isFirstPlugin = !m_isFirstPlugin;
}
}
public class IViewModel : ViewModelBase
{
private ICommand m_testCommand;
public ICommand TestCommand
{
get { return m_testCommand ?? (m_testCommand = new RelayCommand(Test)); }
set { m_testCommand = value; }
}
protected virtual void Test(object parameter) { }
}
public class FirstViewModel : IViewModel
{
protected override void Test(object parameter)
{
MessageBox.Show("On First Plugin.");
}
}
public class SecondViewModel : IViewModel
{
protected override void Test(object parameter)
{
MessageBox.Show("On Second Plugin.");
}
}
<Window x:Class="MvvmInheritence.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Testing" Height="100" Width="180"
xmlns:Local="clr-namespace:MvvmInheritence" WindowStartupLocation="CenterScreen" Background="Transparent">
<Window.DataContext>
<Local:MainWindowViewModel />
</Window.DataContext>
<Grid x:Name="MainGrid">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Button x:Name="TestButton" Content="Test!" Foreground="DarkRed" Background="LightBlue" Height="25" Width="100" Command="{Binding TestCommand, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DataContext="{Binding TestViewModel, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Row="0"/>
<Button x:Name="ChangeButton" Content="Change Plugin" Foreground="DarkRed" Background="LightBlue" Height="25" Width="100" Command="{Binding ChangeCommand, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1"/>
</Grid>
</Window>
这段代码确实可以编译(我做了一些更改使其工作),但出于某种原因,我总是使用“第一个插件”,即使调用了Change
函数,并且ViewModel
被正确更改
我缺少什么?自定义MVVM从创建一个抽象的ViewModelBase类开始,该类实现了
INotifyPropertyChanged
接口
但是,根据您的RelayCommand
注释,我假设您使用的是MVVM Light框架?然后,您的抽象视图模型应该继承MVVM LightsViewModelBase
类,而不是实现INotifyPropertyChanged
RelayCommand将是ViewModelBase的属性,而不是继承自的基类。好的,我发现了问题 在
MainViewModel
类中,应将TestViewModel
属性更改为:
public IViewModel TestViewModel
{
get { return m_testViewModel; }
set
{
m_testViewModel = value;
OnPropertyChanged("NewViewModel");
}
}
致:
你有什么错误?还可以添加基本ViewModel类和RelayCommand类的代码吗?我一直都在这样做。您是在使用MVVM库,还是只是在为您的项目滚动您自己的实现?此外,发布未编译内容的最小示例将大大有助于我们帮助您。很可能您正在实现一个接口,但缺少该方法/属性的抽象声明。更新了我的问题。更新了我的问题。