如何将datacontext设置为其他viewmodel

时间:2015-10-25 13:07:31

标签: c# wpf mvvm

我有两个用于MainWindow的视图模型。 我想在viewmodels之间切换。因此,我有一个主视图模型,允许我在我的第一个和第二个视图模型之间切换:

class MainViewModel : ViewModelBase
{
    private ViewModelBase _currentViewModel;

    public ViewModelBase CurrentViewModel
    {
        get
        {
            return _currentViewModel;
        }
        set
        {
            if (_currentViewModel == value)
                return;
            _currentViewModel = value;
            OnPropertyChanged("CurrentViewModel");
        }
    }

    public ICommand FirstViewCommand { get; private set; }
    public ICommand SecondViewCommand { get; private set; }
    private bool _canExecuteFirstViewCommand;
    private bool _canExecuteSecondViewCommand;

    public MainViewModel(Vokabel model)
    {
        VokabelViewModelDeutschLatein _vokabelViewModelDeutschLatein = new VokabelViewModelDeutschLatein(model);
        VokabelViewModelLateinDeutsch _vokabelViewModelLateinDeutsch = new VokabelViewModelLateinDeutsch(model);
        _canExecuteFirstViewCommand = true;
        _canExecuteSecondViewCommand = true;

        CurrentViewModel = _vokabelViewModelDeutschLatein;
        FirstViewCommand = new CommandHandler(() => ExecuteFirstViewCommand(_vokabelViewModelDeutschLatein),_canExecuteFirstViewCommand);
        SecondViewCommand = new CommandHandler(() => ExecuteSecondViewCommand(_vokabelViewModelLateinDeutsch), _canExecuteSecondViewCommand);
    }

    private void ExecuteFirstViewCommand(VokabelViewModelDeutschLatein _vokabelViewModelDeutschLatein)
    {
        CurrentViewModel = _vokabelViewModelDeutschLatein;
    }

    private void ExecuteSecondViewCommand(VokabelViewModelLateinDeutsch _vokabelViewModelLateinDeutsch)
    {
        CurrentViewModel = _vokabelViewModelLateinDeutsch;
    }
}

在MainWindow的代码中 - 如何将datacontext设置为新的viewmodel?

    public MainWindow()
    {
        Vokabel _Vokabel;
        MainViewModel _MainViewModel;

        InitializeComponent();
        _Vokabel = new Vokabel();
        _MainViewModel = new MainViewModel(_Vokabel.Initialize());
        this.DataContext = _MainViewModel;

    }

在MainWindow.xaml中,我有一个允许我切换到第二个视图模型的按钮:

        <Button Grid.Column="1" Content="Deutsch => Latein" Command="{Binding SecondViewCommand}" />

如果我运行应用程序,则第二个(或第一个)视图模型的datacontext不存在。

1 个答案:

答案 0 :(得分:0)

据我所知,当CurrentViewModel属性发生变化时,您需要动态切换数据上下文。我可以建议你下一个解决方案。使用ContentControl作为主要内容呈现器,并根据该属性的数据更改其datatemplate,该数据窗口显示CurrentViewModel属性定义的当前内容。这是基于您的代码的工作解决方案。  1. Xaml代码:

<Window x:Class="SoContentControlBinding.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:soContentControlBinding="clr-namespace:SoContentControlBinding"
    Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
    <soContentControlBinding:MainViewModel></soContentControlBinding:MainViewModel>
</Window.DataContext>
<Window.Resources>
    <DataTemplate DataType="{x:Type soContentControlBinding:ViewModelBase}">
        <TextBlock Background="Tomato" Text="{Binding Title}"></TextBlock>
    </DataTemplate>
    <DataTemplate DataType="{x:Type soContentControlBinding:VokabelViewModelDeutschLatein}">
        <TextBlock Background="GreenYellow" Text="{Binding Title}"></TextBlock>
    </DataTemplate>
    <DataTemplate DataType="{x:Type soContentControlBinding:VokabelViewModelLateinDeutsch}">
        <TextBlock Background="DeepSkyBlue" Text="{Binding Title}"></TextBlock>
    </DataTemplate>
</Window.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="8*"></RowDefinition>
        <RowDefinition Height="2*"></RowDefinition>
    </Grid.RowDefinitions>
    <ContentControl Content="{Binding CurrentViewModel}"></ContentControl>
    <Button Grid.Row="1" Content="Deutsch => Latein" Command="{Binding SecondViewCommand}"></Button> 
</Grid>

 2.查看模型代码(chanhges与我的基本可观察对象实现有关):

public class MainViewModel : BaseObservableObject
{
    private ViewModelBase _currentViewModel;

    public ViewModelBase CurrentViewModel
    {
        get
        {
            return _currentViewModel;
        }
        set
        {
            if (_currentViewModel == value)
                return;
            _currentViewModel = value;
            OnPropertyChanged("CurrentViewModel");
        }
    }
    public ICommand FirstViewCommand { get; private set; }
    public ICommand SecondViewCommand { get; private set; }
    private bool _canExecuteFirstViewCommand;
    private bool _canExecuteSecondViewCommand;

    public MainViewModel(Vokabel model)
    {
        VokabelViewModelDeutschLatein vokabelViewModelDeutschLatein = new VokabelViewModelDeutschLatein(model);
        VokabelViewModelLateinDeutsch vokabelViewModelLateinDeutsch = new VokabelViewModelLateinDeutsch(model);
        _canExecuteFirstViewCommand = true;
        _canExecuteSecondViewCommand = true;

        CurrentViewModel = vokabelViewModelDeutschLatein;
        FirstViewCommand = new RelayCommand(() => ExecuteFirstViewCommand(vokabelViewModelDeutschLatein));
        SecondViewCommand = new RelayCommand(() => ExecuteSecondViewCommand(vokabelViewModelLateinDeutsch));
    }

    public MainViewModel():this(new Vokabel())
    {

    }

    private void ExecuteFirstViewCommand(VokabelViewModelDeutschLatein vokabelViewModelDeutschLatein)
    {
        CurrentViewModel = vokabelViewModelDeutschLatein;
    }

    private void ExecuteSecondViewCommand(VokabelViewModelLateinDeutsch vokabelViewModelLateinDeutsch)
    {
        CurrentViewModel = vokabelViewModelLateinDeutsch;
    }
}

3。型号代码:

    public class VokabelViewModelLateinDeutsch:ViewModelBase
{
    public VokabelViewModelLateinDeutsch(Vokabel model)
    {
        Title = "VokabelViewModelLateinDeutsch";
    }
}

public class VokabelViewModelDeutschLatein : ViewModelBase
{
    public VokabelViewModelDeutschLatein(Vokabel model)
    {
        Title = "VokabelViewModelDeutschLatein";
    }
}

public class Vokabel
{
}

public class ViewModelBase:BaseObservableObject
{
    private string _title;

    public string Title
    {
        get { return _title; }
        set
        {
            _title = value;
            OnPropertyChanged();
        }
    }
}

4。 BaseObservableObject实现(以及其他mvvm部分):

    public class BaseObservableObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }

    protected virtual void OnPropertyChanged<T>(Expression<Func<T>> raiser)
    {
        var propName = ((MemberExpression)raiser.Body).Member.Name;
        OnPropertyChanged(propName);
    }

    protected bool Set<T>(ref T field, T value, [CallerMemberName] string name = null)
    {
        if (!EqualityComparer<T>.Default.Equals(field, value))
        {
            field = value;
            OnPropertyChanged(name);
            return true;
        }
        return false;
    }
}

public class RelayCommand<T> : ICommand
{
    readonly Action<T> _execute;
    readonly Func<T, bool> _canExecute;

    public event EventHandler CanExecuteChanged;

    public RelayCommand(Action<T> execute, Func<T, bool> canExecute = null)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

    public void RefreshCommand()
    {
        var cec = CanExecuteChanged;
        if (cec != null)
            cec(this, EventArgs.Empty);
    }

    public bool CanExecute(object parameter)
    {
        if (_canExecute == null) return true;
        return _canExecute((T)parameter);
    }

    public void Execute(object parameter)
    {
        _execute((T)parameter);
    }
}

public class RelayCommand : RelayCommand<object>
{
    public RelayCommand(Action execute, Func<bool> canExecute = null)
        : base(_ => execute(),
            _ => canExecute == null || canExecute())
    {

    }
}
  1. 查看何时运行: on running

    的问候,