WPF【11_9】WPF实战-重构与美化(UI 与视图模型的联动,实现INotifyPropertyChanged)-示例

发布于:2025-05-28 ⋅ 阅读:(14) ⋅ 点赞:(0)

--\ViewModels\MainViewModel.cs
public class MainViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    //public List<Customer> Customers { get; set; } = new();
    public ObservableCollection<CustomerViewModel> Customers { get; set; } = new();
    public ObservableCollection<AppointmentViewModel> Appointments { get; set; } = new();

    private CustomerViewModel _selectedCustomer;

    public CustomerViewModel SelectedCustomer
    {
        get => _selectedCustomer; 
        set
        {
            if (value != _selectedCustomer)
            {
                _selectedCustomer = value;
                RaisePropertyChanged(nameof(SelectedCustomer));
                LoadAppointments(SelectedCustomer.Id);
            }
        }
    }

    public void LoadCustomers()
    {
        Customers.Clear();
        using (var db = new AppDbContext())
        {
            // Select * from Customers as c join Appointments as a on c.Id = a. CustomerId
            var customers = db.Customers
                //.Include(c => c.Appointments)
                .ToList();

            foreach (var c in customers)
            {
                Customers.Add(new CustomerViewModel(c));
            }
        }
    }

    public void ClearSelectedCustomer()
    {
        _selectedCustomer = null;
        RaisePropertyChanged(nameof(SelectedCustomer));
    }

    public void SaveCustomer(string name, string idNumber, string address)
    {
        if(SelectedCustomer != null)
        {
            // 更新客户数据
            using (var db = new AppDbContext())
            {
                var customer = db.Customers.Where(c => c.Id == SelectedCustomer.Id).FirstOrDefault();
                customer.Name = name;
                customer.IdNnumber = idNumber;
                customer.Address = address;
                db.SaveChanges();
            }
        }
        else
        {
            // 添加新客户
            using (var db = new AppDbContext())
            {
                var newCustomer = new Customer()
                {
                    Name = name,
                    IdNnumber = idNumber,
                    Address = address
                };
                db.Customers.Add(newCustomer);
                db.SaveChanges();
            }
            LoadCustomers();
        }
    }

    public void LoadAppointments(int customerId)
    {
        Appointments.Clear();
        using (var db = new AppDbContext())
        {
            var appointments = db.Appointments.Where(a => a.CustomerId == customerId).ToList();
            foreach(var a in appointments)
            {
                Appointments.Add(new AppointmentViewModel(a));
            }
        }
    }

    public void AddAppointment(DateTime selectedDate)
    {
        if (SelectedCustomer == null)
        {
            return;
        }

        using (var db = new AppDbContext())
        {
            var newAppointment = new Appointment()
            {
                Time = selectedDate,
                CustomerId = SelectedCustomer.Id
            };
            db.Appointments.Add(newAppointment);
            db.SaveChanges();
        }
        LoadAppointments(SelectedCustomer.Id);
    }
}


--\ViewModels\CustomerViewModel.cs
public class CustomerViewModel
{
    private Customer _customer;

    public CustomerViewModel(Customer customer)
    {
        _customer = customer;
    }

    public int Id { get => _customer.Id; }

    public string Name
    {
        get => _customer.Name; set
        {
            if (_customer.Name != value)
            {
                _customer.Name = value;
            }
        }
    }

    public string IdNnumber
    {
        get => _customer.IdNnumber; set
        {
            if (_customer.IdNnumber != value)
            {
                _customer.IdNnumber = value;
            }
        }
    }

    public string Address
    {
        get => _customer.Address; set
        {
            if (_customer.Address != value)
            {
                _customer.Address = value;
            }
        }
    }
}


--\ViewModels\AppointmentViewModel.cs
public class AppointmentViewModel
{
    private Appointment _appointment;

    public AppointmentViewModel(Appointment appointment)
    {
        _appointment = appointment;
    }

    public int Id { get => _appointment.Id; }

    public DateTime Time
    {
        get => _appointment.Time; 
        set
        {
            if (value != _appointment.Time)
            {
                _appointment.Time = value;
            }
        }
    }
}


--\WPF_CMS\MainWindow.xaml
<Window x:Class="WPF_CMS.MainWindow"
    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:WPF_CMS" 
    xmlns:controls="clr-namespace:WPF_CMS.Controls"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="240"/>
        <ColumnDefinition Width="280"/>
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    
    <!--header-->
    <controls:HeaderControl Grid.ColumnSpan="3"/>

    <StackPanel Grid.Row="1" Grid.Column="0">
        <Button Content="添加客户" Click="ClearSelectedCustomer_Click"/>
        <ListView ItemsSource="{Binding Customers, Mode=OneWay}" DisplayMemberPath="Name" SelectedItem="{Binding SelectedCustomer, Mode=TwoWay}" />
    </StackPanel>

    <StackPanel Grid.Row="1" Grid.Column="1">
        <TextBlock Text="姓名" Margin="10 10 10 0"/>
        <TextBox Name="NameTextBox" Margin="10" Text="{Binding SelectedCustomer.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        <TextBlock Text="身份证" Margin="10 10 10 0"/>
        <TextBox Name="IdTextBox" Margin="10" Text="{Binding SelectedCustomer.IdNnumber, Mode=TwoWay}" />
        <TextBlock Text="地址" Margin="10 10 10 0"/>
        <TextBox Name="AddressTextBox" Margin="10" Text="{Binding SelectedCustomer.Address, Mode=TwoWay}" />
        <Button Content="保存" Margin="10 10 10 30" VerticalAlignment="Bottom" HorizontalAlignment="Left" Click="SaveCustomer_Click" />
    </StackPanel>

    <StackPanel Grid.Row="1" Grid.Column="2">
        <ListView ItemsSource="{Binding Appointments, Mode=TwoWay}" DisplayMemberPath="Time"/>
        <TextBlock Text="添加新预约" />
        <DatePicker Name="AppointmentDatePicker" Margin="10" />
        <Button Content="预约" Click="AddAppointment_Click" />
    </StackPanel>
    
</Grid>
</Window>

--\WPF_CMS\MainWindow.xaml.cs
public partial class MainWindow : Window
{
    private MainViewModel _viewModel;
    public MainWindow()
    {
        InitializeComponent();
        _viewModel = new MainViewModel();

        _viewModel.LoadCustomers();

        DataContext = _viewModel;
        //ShowCustomers();
    }

    private void ClearSelectedCustomer_Click(object sender, RoutedEventArgs e)
    {
        _viewModel.ClearSelectedCustomer();
    }

    private void SaveCustomer_Click(object sender, RoutedEventArgs e)
    {
        try
        {
            string name = NameTextBox.Text.Trim(); 
            string idNumber = IdTextBox.Text.Trim(); 
            string address = AddressTextBox.Text.Trim();

            _viewModel.SaveCustomer(name, idNumber, address);
        }
        catch (Exception error)
        {
            MessageBox.Show(error.ToString());
        }
    }

    private void AddAppointment_Click(object sender, RoutedEventArgs e)
    {
        try
        {
            DateTime time = DateTime.Parse(AppointmentDatePicker.Text);
            _viewModel.AddAppointment(time);
        }
        catch (Exception error)
        {
            MessageBox.Show(error.ToString());
        }
    }
}