WPF【11_11】WPF实战-重构与美化(配置Material UI框架)-示例

--\App.xaml

<Application x:Class="WPF_CMS.App"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:local="clr-namespace:WPF_CMS"

xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"

StartupUri="MainWindow.xaml">

<Application.Resources>

<ResourceDictionary>

<ResourceDictionary.MergedDictionaries>

<materialDesign:BundledTheme BaseTheme="Light" PrimaryColor="DeepPurple" SecondaryColor="Lime" />

<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />

</ResourceDictionary.MergedDictionaries>

</ResourceDictionary>

</Application.Resources>

</Application>

--\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"

xmlns:MaterialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"

xmlns:alex="clr-namespace:WPF_CMS.ArrachedProperties"

mc:Ignorable="d"

Title="CMS客户管理系统" Height="600" Width="900" Background="Transparent" AllowsTransparency="True" WindowStyle="None" WindowStartupLocation="CenterScreen" FontFamily="Cambria">

<Border Background="White" CornerRadius="30">

<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" Width="192" Margin="10"/>

<ListView ItemsSource="{Binding Customers, Mode=OneWay}" DisplayMemberPath="Name" SelectedItem="{Binding SelectedCustomer, Mode=TwoWay}" />

</StackPanel>

<MaterialDesign:Card Grid.Row="1" Grid.Column="1" Width="250" Height="440" Margin="10">

<StackPanel >

<Border Margin="10" CornerRadius="20" Background="#FFFFEEFA">

<Image Source="/Images/cartoon.png" Stretch="Uniform" Height="150" />

</Border>

<TextBox

Name="NameTextBox"

Margin="10"

Style="{StaticResource MaterialDesignOutlinedTextBox}"

MaterialDesign:HintAssist.Hint="姓名"

Text="{Binding SelectedCustomer.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

<TextBox

Name="IdTextBox"

Margin="10"

Style="{StaticResource MaterialDesignOutlinedTextBox}"

MaterialDesign:HintAssist.Hint="身份证"

Text="{Binding SelectedCustomer.IdNnumber, Mode=TwoWay}" />

<TextBox

Name="AddressTextBox"

Margin="10"

Style="{StaticResource MaterialDesignOutlinedTextBox}"

MaterialDesign:HintAssist.Hint="地址"

Text="{Binding SelectedCustomer.Address, Mode=TwoWay}" />

<Button Content="保存" Margin="10 10 10 30" VerticalAlignment="Bottom" HorizontalAlignment="Left" Click="SaveCustomer_Click" />

</StackPanel>

</MaterialDesign:Card>

<MaterialDesign:Card Grid.Row="1" Grid.Column="2" Width="310" Margin="35, 30 35, 30">

<StackPanel Grid.Row="1" Grid.Column="2">

<!--<ListView ItemsSource="{Binding Appointments, Mode=TwoWay}" DisplayMemberPath="Time"/>-->

<Calendar Name="AppointmentCalender" Height="320" Width="300" alex:CalendarAttachedProperties.RegisterBlackoutDates="{Binding Appointments, Mode=OneWay}" SelectedDate="{Binding SelectedDate, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">

</Calendar>

<Button Content="预约" Click="AddAppointment_Click" Width="190" Margin="10" />

</StackPanel>

</MaterialDesign:Card>

</Grid>

</Border>

</Window>

--\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

{

_viewModel.AddAppointment();

}

catch (Exception error)

{

MessageBox.Show(error.ToString());

}

}

}

--\ArrachedProperties\CalendarAttachedProperties.cs

namespace WPF_CMS.ArrachedProperties

{

// Adds a collection of command bindings to a date picker's existing BlackoutDates collection, since the collections are immutable and can't be bound to otherwise.

// Usage: <DatePicker hacks:AttachedProperties.RegisterBlackoutDates="{Binding BlackoutDates}" >

public class CalendarAttachedProperties : DependencyObject

{

#region Attributes

private static readonly List<Calendar> _calendars = new List<Calendar>();

private static readonly List<DatePicker> _datePickers = new List<DatePicker>();

#endregion

#region Dependency Properties

public static DependencyProperty RegisterBlackoutDatesProperty = DependencyProperty.RegisterAttached("RegisterBlackoutDates", typeof(ObservableCollection<DateTime>), typeof(CalendarAttachedProperties), new PropertyMetadata(null, OnRegisterCommandBindingChanged));

public static void SetRegisterBlackoutDates(DependencyObject d, ObservableCollection<DateTime> value)

{

d.SetValue(RegisterBlackoutDatesProperty, value);

}

public static ObservableCollection<DateTime> GetRegisterBlackoutDates(DependencyObject d)

{

return (ObservableCollection<DateTime>)d.GetValue(RegisterBlackoutDatesProperty);

}

#endregion

#region Event Handlers

private static void CalendarBindings_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)

{

ObservableCollection<DateTime> blackoutDates = sender as ObservableCollection<DateTime>;

Calendar calendar = _calendars.First(c => c.Tag == blackoutDates);

if (e.Action == NotifyCollectionChangedAction.Reset)

{

calendar.BlackoutDates.Clear();

}

if (e.Action == NotifyCollectionChangedAction.Add)

{

foreach (DateTime date in e.NewItems)

{

calendar.BlackoutDates.Add(new CalendarDateRange(date));

}

}

}

private static void DatePickerBindings_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)

{

ObservableCollection<DateTime> blackoutDates = sender as ObservableCollection<DateTime>;

DatePicker datePicker = _datePickers.First(c => c.Tag == blackoutDates);

if (e.Action == NotifyCollectionChangedAction.Add)

{

foreach (DateTime date in e.NewItems)

{

datePicker.BlackoutDates.Add(new CalendarDateRange(date));

}

}

}

#endregion

#region Private Methods

private static void OnRegisterCommandBindingChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)

{

Calendar calendar = sender as Calendar;

if (calendar != null)

{

ObservableCollection<DateTime> bindings = e.NewValue as ObservableCollection<DateTime>;

if (bindings != null)

{

if (!_calendars.Contains(calendar))

{

calendar.Tag = bindings;

_calendars.Add(calendar);

}

calendar.BlackoutDates.Clear();

foreach (DateTime date in bindings)

{

calendar.BlackoutDates.Add(new CalendarDateRange(date));

}

bindings.CollectionChanged += CalendarBindings_CollectionChanged;

}

}

else

{

DatePicker datePicker = sender as DatePicker;

if (datePicker != null)

{

ObservableCollection<DateTime> bindings = e.NewValue as ObservableCollection<DateTime>;

if (bindings != null)

{

if (!_datePickers.Contains(datePicker))

{

datePicker.Tag = bindings;

_datePickers.Add(datePicker);

}

datePicker.BlackoutDates.Clear();

foreach (DateTime date in bindings)

{

datePicker.BlackoutDates.Add(new CalendarDateRange(date));

}

bindings.CollectionChanged += DatePickerBindings_CollectionChanged;

}

}

}

}

#endregion

}

}

--\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<DateTime> Appointments { get; set; } = new();

private DateTime? _selectedDate;

public DateTime? SelectedDate { get => _selectedDate;

set

{

if(_selectedDate != value)

{

_selectedDate = value;

RaisePropertyChanged(nameof(SelectedDate));

}

} }

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(a.Time);

}

}

}

public void AddAppointment()

{

if (SelectedCustomer == null)

{

return;

}

using (var db = new AppDbContext())

{

var newAppointment = new Appointment()

{

Time = SelectedDate.Value,

CustomerId = SelectedCustomer.Id

};

db.Appointments.Add(newAppointment);

db.SaveChanges();

}

SelectedDate = null;

LoadAppointments(SelectedCustomer.Id);

}

}

最终效果示例图

相关推荐
陈奕昆44 分钟前
2.1HarmonyOS NEXT开发工具链进阶:DevEco Studio深度实践
华为·wpf·harmonyos
telunsidianziqin3 小时前
特伦斯 S75 电钢琴:重构演奏美学的极致表达
重构
Dr.多喝热水3 小时前
WPF prism
windows·wpf
向哆哆4 小时前
Java代码重构:如何提升项目的可维护性和扩展性?
java·python·重构
FuckPatience6 小时前
UI 资源整合
ui·c#
zhonghuagongren8 小时前
高考加油!UI界面生成器!
python·学习·ui·高考
weixin_5498083614 小时前
易路 iBuilder:解构企业 AI 落地困境,重构智能体时代生产力范式
人工智能·重构
Hare_bai14 小时前
WPF响应式UI的基础:INotifyPropertyChanged
ui·c#·wpf·xaml
上元星如雨14 小时前
WPF 全局加载界面、多界面实现渐变过渡效果
wpf
Hare_bai14 小时前
WPF的布局核心:网格布局(Grid)
ui·c#·wpf·交互·xaml