创建抽象ViewModels wpf

时间:2015-12-29 13:37:34

标签: c# wpf inheritance viewmodel relaycommand

我正在尝试创建一个抽象的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函数,我也总是得到“On First Plugin”,ViewModel已正确更改。

我错过了什么?

2 个答案:

答案 0 :(得分:1)

自定义MVVM首先创建一个实现INotifyPropertyChanged接口的抽象ViewModelBase类。

但是,基于您的RelayCommand评论,我假设您正在使用MVVM Light框架?然后,而不是实现INotifyPropertyChanged,您的抽象ViewModel应该继承自MVVM Lights ViewModelBase类。

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

答案 1 :(得分:-1)

好的,我发现了故障。

enum Name<T> where T:Borrow<str> { Single(T), Double(T, T), } // these both work now let _a1 = Name::Single("hello"); let _a2 = Name::Double(String::from("hello"), String::from("world")); 类中,MainViewModel属性应更改为:

TestViewModel

要:

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