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

--\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());

}

}

}

相关推荐
故渊at2 小时前
第二板块:Android 四大组件标准化学理 | 第十二篇:四大组件全景总结与系统服务(System Server)架构
android·架构·wpf·四大组件·system service
xiami_world3 小时前
2026年UI/UX设计工具私有化部署方案深度解析
人工智能·ui·ai·产品经理·ux
Agilex松灵机器人4 小时前
ROS 机械臂开发效率低?用 Agent + 具身智能重构开发流程
重构·机器人·自动驾驶
川石课堂软件测试4 小时前
UI自动化测试|XPath元素定位实践
功能测试·测试工具·jmeter·microsoft·ui·postman·harmonyos
伶俜665 小时前
# [特殊字符] 零基础学 ArkUI 数据持久化(专题三):5 种存储方案深度对比
学习·华为·wpf·harmonyos
川石课堂软件测试6 小时前
UI自动化测试|CSS元素定位实践
css·测试工具·ui·fiddler·单元测试·appium·harmonyos
IT策士6 小时前
Redis 从入门到精通:数据结构String 与键管理
数据结构·redis·wpf
AC赳赳老秦6 小时前
技术文章素材收集自动化:用 OpenClaw 自动爬取行业资讯、技术热点、优质文章
运维·开发语言·python·自动化·wpf·deepseek·openclaw
加号37 小时前
【WPF】 Storyboard 故事板动画设计深度解析
wpf
人工智能培训7 小时前
用知识图谱重构搜索引擎
大数据·人工智能·3d·重构·知识图谱·agent