Моя идея состоит в том, чтобы иметь окно с двумя элементами управления содержимым, которые меняются в разных представлениях. Например, мое приложение может начинаться с изображения приветствия в одном элементе управления контентом и кнопки ввода / выхода в другом. При нажатии кнопки ввода я хочу изменить вид приветствия на другой вид, а кнопки входа / выхода - на 3 другие кнопки.
Моя текущая проблема заключается в том, что попытка изменить представление приветствия нажатием кнопки ввода не работает, если я помещаю его в пользовательский элемент управления и размещаю его в элементе управления контентом. Я думаю, потому что я на самом деле создаю новый экземпляр моего MainViewModel
вместо ссылки на существующий, но я не совсем уверен.
Как я могу сделать это, когда я нажимаю на мою кнопку в BottomPanelTwoButtonsView
, мои HomeView
изменяются на TestView
?
Всего 4 просмотров:
HomeView
- экран приветствия
TestView
- другой вид
BottomPanelTwoButtonsView
- кнопки входа / выхода
BottomPanelThreeButtonsView
- еще 3 кнопки
Вот основной код, который у меня есть:
App.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>
* ** 1038 1039 * MainViewModel.cs * ** 1040 1041 *
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>
IPageViewModel.cs
public interface IPageViewModel
{
string Name { get; }
}
ObservableObject.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);
}
}
}
RelayCommand.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);
}
}