我有两个用于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不存在。
答案 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())
{
}
}