正在创建抽象ViewModels wpf

本文关键字:ViewModels wpf 抽象 创建 | 更新日期: 2023-09-27 18:28:19

我正在尝试创建一个抽象ViewModel类,以及几个将继承抽象ViewModel并实现它的ViewModel类。

到目前为止,我使用的是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);
    }
}

ViewModelsBase类:

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

MainViewModel类:

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

IViewModel类:

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) { }
}

FirstViewModel类:

public class FirstViewModel : IViewModel
{
    protected override void Test(object parameter)
    {
        MessageBox.Show("On First Plugin.");
    }
}

SecondViewModel类:

public class SecondViewModel : IViewModel
{
    protected override void Test(object parameter)
    {
        MessageBox.Show("On Second Plugin.");
    }
}

Xaml:

<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,我也总是得到"On First Plugin"。

我错过了什么?

正在创建抽象ViewModels wpf

Custom MVVM从创建一个实现INotifyPropertyChanged接口的抽象ViewModelBase类开始。

然而,根据您的RelayCommand评论,我认为您使用的是MVVM Light框架?然后,您的抽象ViewModel应该继承MVVM Lights ViewModelBase类,而不是实现INotifyPropertyChanged

RelayCommands将是ViewModelBase的属性,而不是从中继承的基类。

好的,我发现了故障。

MainViewModel类中,TestViewModel属性应更改为:

public IViewModel TestViewModel
{
    get { return m_testViewModel; }
    set
    {
        m_testViewModel = value;
        OnPropertyChanged("NewViewModel");
    }
}

收件人:

public IViewModel TestViewModel
{
    get { return m_testViewModel; }
    set
    {
        m_testViewModel = value;
        OnPropertyChanged("TestViewModel");
    }
}