【问题标题】:How to set datacontext to a different viewmodel如何将数据上下文设置为不同的视图模型
【发布时间】:2015-10-25 23:22:26
【问题描述】:

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

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 设置为新的视图模型?

    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}" />

如果我运行应用程序,第二个(或第一个)视图模型的数据上下文不存在。

【问题讨论】:

    标签: c# wpf mvvm


    【解决方案1】:

    据我所知,当 CurrentViewModel 属性发生更改时,您需要动态切换数据上下文。我可以建议你下一个解决方案。使用 ContentControl 作为主要内容呈现器,并根据该属性的数据更改其呈现由 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. 查看模型代码(更改与我的基本可观察对象实现有关):

    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. 查看运行时间:

      问候,

    【讨论】:

      猜你喜欢
      • 2021-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-19
      • 2013-02-22
      • 1970-01-01
      • 2023-03-29
      • 2023-03-07
      相关资源
      最近更新 更多