在C#中實現MVVM(Model-View-ViewModel)架構時,可以總結以下幾個關鍵知識點,并通過具體的代碼示例來進行說明。
?
1. 模型 (Model)
模型包含應用程序中的數據和業務邏輯。通常與數據庫交互。
public class User
{
? ? public int Id { get; set; }
? ? public string Name { get; set; }
? ? public int Age { get; set; }
}
?
2. 視圖 (View)
視圖是UI部分,包括窗口、控件以及布局等。
<Window x:Class="MVVMExample.MainWindow"
? ? ? ? xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
? ? ? ? xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
? ? ? ? Title="MainWindow" Height="350" Width="525">
? ? <Grid>
? ? ? ? <TextBox x:Name="txtName" Margin="10" Text="{Binding User.Name, UpdateSourceTrigger=PropertyChanged}" />
? ? ? ? <TextBox x:Name="txtAge" Margin="10" HorizontalAlignment="Right" Text="{Binding User.Age, StringFormat={} {0:D2}, UpdateSourceTrigger=PropertyChanged}" />
? ? </Grid>
</Window>
?
3. 視圖模型 (ViewModel)
視圖模型封裝了應用程序的數據邏輯和業務規則,并且負責與View進行交互,提供給View顯示所需的數據以及處理用戶輸入。
using System.ComponentModel;
?
public class UserViewModel : INotifyPropertyChanged
{
? ? private User _user = new User();
? ??
? ? public UserViewModel()
? ? {
? ? ? ? _user.Name = "John Doe";
? ? ? ? _user.Age = 30;
? ? }
?
? ? public User User
? ? {
? ? ? ? get => _user;
? ? ? ? set
? ? ? ? {
? ? ? ? ? ? if (_user != value)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? _user = value;
? ? ? ? ? ? ? ? OnPropertyChanged("User");
? ? ? ? ? ? }
? ? ? ? }
? ? }
?
? ? public event PropertyChangedEventHandler PropertyChanged;
?
? ? protected void OnPropertyChanged(string name)
? ? {
? ? ? ? PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
? ? }
}
?
4. 數據綁定 (Data Binding)
數據綁定是MVVM模式的核心。它可以自動同步ViewModel中的屬性到視圖上對應的控件。
<Window.DataContext>
? ? <local:UserViewModel />
</Window.DataContext>
?
<!-- 其他 UI 定義 -->
?
5. 命令 (Command)
命令用于在View和ViewModel之間傳遞用戶操作。
using System.Windows.Input;
?
public class RelayCommand : ICommand
{
? ? private readonly Action<object> _execute;
? ? private readonly Func<object, bool> _canExecute;
?
? ? public RelayCommand(Action<object> execute) : this(execute, null) { }
?
? ? public RelayCommand(Action<object> execute, Func<object, bool> canExecute)
? ? {
? ? ? ? _execute = execute ?? throw new ArgumentNullException(nameof(execute));
? ? ? ? _canExecute = canExecute;
? ? }
?
? ? public event EventHandler CanExecuteChanged
? ? {
? ? ? ? add => CommandManager.RequerySuggested += value;
? ? ? ? remove => CommandManager.RequerySuggested -= value;
? ? }
?
? ? public bool CanExecute(object parameter)
? ? {
? ? ? ? return _canExecute == null || _canExecute(parameter);
? ? }
?
? ? public void Execute(object parameter)
? ? {
? ? ? ? _execute?.Invoke(parameter);
? ? }
}
?
6. 命令綁定 (Command Binding)
<Button Content="Click Me" Command="{Binding MyCommand}" />
public class UserViewModel : INotifyPropertyChanged
{
? ? // ... 其他代碼
?
? ? public ICommand MyCommand { get; private set; }
?
? ? public UserViewModel()
? ? {
? ? ? ? MyCommand = new RelayCommand(param =>
? ? ? ? {
? ? ? ? ? ? MessageBox.Show("Button clicked!");
? ? ? ? });
? ? }
}
?
7. 資源字典 (Resource Dictionaries)
資源字典用于存儲如顏色、字體、樣式和模板之類的可重用資源。
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml"
? ? ? ? ? ? ? ? ? ? ?xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
?
? ? <Style x:Key="MyTextBoxStyle" TargetType="{x:Type TextBox}">
? ? ? ? <Setter Property="Background" Value="LightBlue"/>
? ? ? ? <Setter Property="BorderBrush" Value="DarkGray"/>
? ? ? ? <Setter Property="FontSize" Value="14"/>
? ? </Style>
?
</ResourceDictionary>
<Window.Resources>
? ? <ResourceDictionary Source="/Resources/Styles.xaml"/>
</Window.Resources>
?
<!-- 使用資源字典中的樣式 -->
<TextBox Style="{StaticResource MyTextBoxStyle}" />
?
8. 自定義控件 (Custom Controls)
自定義控件允許擴展現有的WPF控件,以適應特定的UI需求。
using System.Windows.Controls;
using System.Windows;
?
public class CustomTextBox : TextBox
{
? ? static CustomTextBox()
? ? {
? ? ? ? DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomTextBox), new FrameworkPropertyMetadata(typeof(CustomTextBox)));
? ? }
?
? ? public static readonly DependencyProperty IsReadOnlyProperty =
? ? ? ? DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(CustomTextBox));
?
? ? public bool IsReadOnly
? ? {
? ? ? ? get { return (bool)GetValue(IsReadOnlyProperty); }
? ? ? ? set { SetValue(IsReadOnlyProperty, value); }
? ? }
}
?
9. 視圖加載與生命周期管理
<Window x:Class="MVVMExample.MainWindow"
? ? ? ? xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
? ? ? ? xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
? ? ? ? Title="MainWindow" Height="350" Width="525">
? ? <Grid>
? ? ? ? <!-- UI 元素 -->
? ? </Grid>
?
? ? <Window.Resources>
? ? ? ? <local:UserViewModel x:Key="MainVM"/>
? ? </Window.Resources>
?
? ? <Window.DataContext>
? ? ? ? <Binding Source="{StaticResource MainVM}"/>
? ? </Window.DataContext>
</Window>
?
10. 視圖模型中的依賴注入
public class UserViewModel : INotifyPropertyChanged
{
? ? private readonly IUserService _userService;
?
? ? public UserViewModel(IUserService userService)
? ? {
? ? ? ? _userService = userService;
? ? }
?
? ? // 其他代碼...
}
?
使用Unity容器進行依賴注入:
using Unity;
using System.Windows.Threading;
?
public class AppBootstrapper : UnityBootstrapper
{
? ? protected override void InitializeShell()
? ? {
? ? ? ? base.InitializeShell();
? ? ? ??
? ? ? ? var shell = (MainWindow)Shell;
? ? ? ? var viewModel = Container.Resolve<UserViewModel>();
? ? ? ? shell.DataContext = viewModel;
? ? }
?
? ? protected override DependencyObject CreateShell()
? ? {
? ? ? ? return new MainWindow();
? ? }
}
以上是對C#中MVVM模式的關鍵知識點及對應的代碼示例。通過這些例子,你可以更好地理解和實現MVVM架構。
?