从用户控件内部更改视图



我的想法是让一个包含 2 个内容控件的窗口更改为不同的视图。例如,我的应用可能从一个内容控件中的欢迎图像开始,而在另一个内容控件中以进入/退出按钮开头。单击输入按钮时,我想将欢迎视图更改为其他视图,将进入/退出按钮更改为其他 3 个按钮。

我目前的问题是,如果我将其放在用户控件中并将其托管在内容控件中,则尝试通过单击 Enter 按钮更改欢迎视图似乎不起作用。我的猜测是因为我实际上是在创建MainViewModel的新实例,而不是引用现有实例,但我不完全确定。

当我点击我的按钮时,我怎么能做到这一点BottomPanelTwoButtonsView我的HomeView更改为TestView

总共有4个视图:

HomeView- 欢迎屏幕

TestView- 其他一些视图

BottomPanelTwoButtonsView- 进入/退出按钮

BottomPanelThreeButtonsView- 其他 3 个按钮

这是我的基本代码:

应用xaml.cs

public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow app = new MainWindow();
MainViewModel context = new MainViewModel();
app.DataContext = context;
app.Show();
}
}

MainWindow.xaml

<Window x:Class="MyApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:localViewModels="clr-namespace:MyApp.ViewModels"
xmlns:localViews="clr-namespace:MyApp.Views"
mc:Ignorable="d"
Name="RootWindow"
WindowStyle="None" ResizeMode="NoResize"
Topmost="True"
WindowStartupLocation="CenterScreen"
WindowState="Maximized"
Background="{StaticResource BackgroundSolidColorBrush}"
ToolBarTray.IsLocked="True"
NumberSubstitution.Substitution="European"
Title="MyApp" Height="1920" Width="1080">
<Window.Resources>
<DataTemplate DataType="{x:Type localViewModels:HomeViewModel}">
<localViews:HomeView />
</DataTemplate>
<DataTemplate DataType="{x:Type localViewModels:TestViewModel}">
<localViews:TestView />
</DataTemplate>
<DataTemplate DataType="{x:Type localViewModels:BottomPanelTwoButtonsViewModel}">
<localViews:BottomPanelTwoButtons />
</DataTemplate>
<DataTemplate DataType="{x:Type localViewModels:BottomPanelThreeButtonsViewModel}">
<localViews:BottomPanelThreeButtons />
</DataTemplate>
</Window.Resources>
<DockPanel Background="White">           
<ContentControl Content="{Binding CurrentBottomPanelViewModel}" DockPanel.Dock="Bottom" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Height="96" Width="1080">                
</ContentControl>
<ContentControl Content="{Binding CurrentPageViewModel}" HorizontalAlignment="Stretch" VerticalAlignment="Top" HorizontalContentAlignment="Stretch" Height="1824" Width="1080">               
</ContentControl>
</DockPanel>
</Window>

主视图模型.cs

public class MainViewModel : ObservableObject
{
#region Fields
private ICommand _changePageCommand;
private IPageViewModel _currentPageViewModel;
private IBottomPanelViewModel _currentBottomPanelViewModel;
private ObservableCollection<IPageViewModel> _pageViewModels;
#endregion
public MainViewModel()
{
CurrentPageViewModel = new HomeViewModel();
CurrentBottomPanelViewModel = new BottomPanelTwoButtonsViewModel();
//CurrentBottomPanelViewModel = new BottomPanelThreeButtonsViewModel();
PageViewModels.Add(new ScreeningsScheduleViewModel());
PageViewModels.Add(new TestViewModel());
PageViewModels.Add(CurrentPageViewModel);
}
#region Properties / Commands
public ICommand ChangePageCommand
{
get
{
if (_changePageCommand == null)
{
_changePageCommand = new RelayCommand(
p => ChangeViewModel((IPageViewModel)p),
p => p is IPageViewModel);
}
return _changePageCommand;
}
}
public ObservableCollection<IPageViewModel> PageViewModels
{
get
{
if (_pageViewModels == null)
{
_pageViewModels = new ObservableCollection<IPageViewModel>();
}
return _pageViewModels;
}
set
{
_pageViewModels = value;
OnPropertyChanged("PageViewModels");
}
}
public IPageViewModel CurrentPageViewModel
{
get => _currentPageViewModel;
set
{
if (_currentPageViewModel != value)
{
_currentPageViewModel = value;
OnPropertyChanged("CurrentPageViewModel");
}
}
}
public IBottomPanelViewModel CurrentBottomPanelViewModel
{
get => _currentBottomPanelViewModel;
set
{
if (_currentBottomPanelViewModel != value)
{
_currentBottomPanelViewModel = value;
OnPropertyChanged("CurrentBottomPanelViewModel");
}
}
}
#endregion
#region Methods
private void ChangeViewModel(IPageViewModel viewModel)
{                
if (!PageViewModels.Contains(viewModel))
{
PageViewModels.Add(viewModel);
}
CurrentPageViewModel = PageViewModels
.FirstOrDefault(vm => vm == viewModel);    
}
#endregion
}

BottomPanelTwoButtonsView.xaml

<UserControl x:Class="MyApp.Views.BottomPanelTwoButtons"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mvm="clr-namespace:MyApp"
mc:Ignorable="d" 
d:DesignHeight="450" d:DesignWidth="1080">
<UserControl.DataContext>
<mvm:MainViewModel/>
</UserControl.DataContext>
<Grid Height="96" Background="White" Width="1080">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Grid.Column="0" 
Content="1"
Command="{Binding DataContext.ChangePageCommand, Source={RelativeSource Mode=FindAncestor, AncestorType={x:Type mvm:MainViewModel}}, Mode=TwoWay}"
CommandParameter="{Binding PageViewModels[2]}"
IsEnabled="True"
Style="{StaticResource RoundCornerButtonCyanFilledBig}" 
/>
<Button Grid.Column="1" Style="{StaticResource RoundCornerButtonMagentaFilledBig}"/>
</Grid>
</UserControl>

IPageView模型.cs

public interface IPageViewModel
{
string Name { get; }
}

可观察对象.cs

public abstract class ObservableObject : INotifyPropertyChanged
{
[Conditional("DEBUG")]
[DebuggerStepThrough]
public virtual void VerifyPropertyName(string propertyName)
{        
if (TypeDescriptor.GetProperties(this)[propertyName] == null)
{
string msg = "Invalid property name: " + propertyName;
if (!ThrowOnInvalidPropertyName)
{
Debug.Fail(msg);
}
else
{
throw new Exception(msg);
}
}
}
protected virtual bool ThrowOnInvalidPropertyName { get; private set; }
public virtual void RaisePropertyChanged(string propertyName)
{
VerifyPropertyName(propertyName);
OnPropertyChanged(propertyName);
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
this.VerifyPropertyName(propertyName);
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
}

中继命令.cs

public class RelayCommand : ICommand
{
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute ?? throw new ArgumentNullException("execute");
_canExecute = canExecute;
}
[DebuggerStepThrough]
public bool CanExecute(object parameters)
{
return _canExecute == null ? true : _canExecute(parameters);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameters)
{
_execute(parameters);
}
}

我想你的问题在BottomPanelTwoButtonsView.xaml

您有以下行:

<UserControl.DataContext>
<mvm:MainViewModel/>
</UserControl.DataContext>

所以你正在覆盖在 Window 中定义的数据上下文。MainWindow 的资源

最新更新