[英]Binding ContentControl to the ApplicationViewModel that will determine which user control to view?
我是WPF的新手,而C#編程(通常是編程)的新手,我正在嘗試開發WPF應用程序。
我已經嘗試過類似的幾篇文章,但是我似乎找不到為什么不起作用的答案。
因此,我很難理解MVVM體系結構,在綁定到單個<ContentControl />
多個用戶控件之間進行切換的方式和要求。 到目前為止,據我所了解和閱讀的是,我必須像這樣綁定視圖模型:
<ContentControl Content="{Binding ApplicationViewModel}"/>
所以這是我想要實現的目標:
一個ApplicationWindow.xaml
帶有在左側的側邊欄菜單,在應用程序運行時將始終顯示,並在剩余空間上顯示<ContentControl/>
。 側欄菜單上顯示的按鈕為:
MainView.xaml
用戶控件,應為默認用戶控件) SettingsView.xaml
用戶控件) 我知道我需要將按鈕綁定到ICommand
命令,並且我了解RelayCommand.cs
類的概念。 因此,讓我們進入我的想法的簡化代碼,弄清楚我需要了解的內容以及在過程中可能被誤解的內容。
MainView.xaml
和SettingsView.xaml
包含的內容現在並不重要,因為我只是想弄清楚如何在應用程序中顯示它們。
這是ApplicationWindow.xaml
:
<Window x:Class="WpfApp1.ApplicationWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
xmlns:v="clr-namespace:WpfApp1.View"
xmlns:vm="clr-namespace:WpfApp1.ViewModel"
mc:Ignorable="d"
Title="ApplicationWindow" Height="1080" Width="1920"
WindowStyle="None" WindowState="Maximized">
<Window.Resources>
<DataTemplate DataType="{x:Type vm:MainViewModel}">
<v:MainView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SettingsViewModel}">
<v:SettingsView/>
</DataTemplate>
</Window.Resources>
<DockPanel>
<!--Menu bar on the left-->
<Border DockPanel.Dock="Left">
<StackPanel Orientation="Vertical" Background="Gray" Width="120">
<Button Content="Main" Command="{Binding ShowMainCommand}"/>
<Button Content="Settings" Command="{Binding ShowSettingsCommand}"/>
<Button Content="Exit" Command="{Binding ExitApplicationCommand}"/>
</StackPanel>
</Border>
<!--The content control that view the current view-->
<ContentControl Content="{Binding ApplicationViewModel}"/>
</DockPanel>
</Window>
注意:通過重寫OnStartup()方法,將DataContext在App.xaml.cs中設置為ApplicationViewModel.cs
。
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
ApplicationWindow app = new ApplicationWindow
{
DataContext = new ApplicationViewModel()
};
app.Show();
}
}
這是ApplicationViewModel.cs
:
public class ApplicationViewModel : ViewModelBase
{
#region Fields
private List<ViewModelBase> _viewModels;
private ViewModelBase _currentViewModel;
private ICommand _showMainCommand;
private ICommand _showSettingsCommand;
private ICommand _exitApplicationCommmand;
#endregion
#region Constructor
public ApplicationViewModel()
{
ViewModels = new List<ViewModelBase>
{
new MainViewModel(),
new SettingsViewModel()
};
CurrentViewModel = ViewModels[0];
}
#endregion
#region Public Properties
public List<ViewModelBase> ViewModels
{
get
{
return _viewModels;
}
set
{
if (_viewModels != value)
{
_viewModels = value;
OnPropertyChanged(nameof(ViewModels));
}
}
}
public ViewModelBase CurrentViewModel
{
get
{
return _currentViewModel;
}
set
{
if(_currentViewModel != value)
{
_currentViewModel = value;
OnPropertyChanged(nameof(CurrentViewModel));
}
}
}
#endregion
#region Commands
public ICommand ShowMainCommand
{
get
{
if(_showMainCommand == null)
{
_showMainCommand = new RelayCommand(action => ShowMain());
}
return _showMainCommand;
}
}
public ICommand ShowSettingsCommand
{
get
{
if (_showSettingsCommand == null)
{
_showSettingsCommand = new RelayCommand(action => ShowSettings());
}
return _showSettingsCommand;
}
}
public ICommand ExitApplicationCommand
{
get
{
if (_exitApplicationCommmand == null)
{
_exitApplicationCommmand = new RelayCommand(action => ExitApplication());
}
return _exitApplicationCommmand;
}
}
#endregion
#region Private Methods
private void ShowMain()
{
CurrentViewModel = ViewModels[0];
}
private void ShowSettings()
{
CurrentViewModel = ViewModels[1];
}
private void ExitApplication()
{
MessageBoxResult result = MessageBox.Show("Are you sure you want to exit?", "Exit", MessageBoxButton.YesNo);
if (result == MessageBoxResult.Yes)
{
System.Windows.Application.Current.Shutdown();
}
}
#endregion
}
因此,據我了解, ApplicationWindow.xaml
應該能夠確定從CurrentViewModel
設置為顯示哪個視圖。
為了提供信息(或缺少信息),以下是ViewModelBase.cs
:
public class ViewModelBase : INotifyPropertyChanged
{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
和RelayCommand.cs
:
public class RelayCommand : ICommand
{
#region Fields
private readonly Action<object> _execute;
private readonly Predicate<object> _canExecute;
#endregion
#region Constructors
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
public RelayCommand(Action<object> execute) : this(execute, null)
{
}
#endregion
#region ICommand
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);
}
#endregion
}
我希望我對這一點的思考過程對您很清楚,並且你們中的一位聰明的程序員可以幫助解決這個問題,並幫助我理解為什么這種情況沒有達到我的期望。
如果我想做的事情比埃隆·馬斯克(Elon Musk)的使生活成為多行星的項目更難,請隨時解釋原因,並向我建議一種更好的方法
您的Content控件綁定應指向您在切換ViewModels時更改的實際屬性
<ContentControl Content="{Binding CurrentViewModel}"/>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.