refactor: refactor data struct for resolving binding error

This commit is contained in:
2025-09-06 18:20:43 +08:00
parent aed8ab57fb
commit 95d1db17af
13 changed files with 384 additions and 103 deletions

View File

@ -4,9 +4,9 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:HFUTCourseSimulation.Dialog" xmlns:local="clr-namespace:HFUTCourseSimulation.Dialog"
xmlns:userdata="clr-namespace:HFUTCourseSimulation.Kernel.UserData" xmlns:uidata="clr-namespace:HFUTCourseSimulation.Kernel.Data.Ui"
mc:Ignorable="d" mc:Ignorable="d"
d:DataContext="{d:DesignInstance userdata:Course}" d:DataContext="{d:DesignInstance uidata:Course}"
x:Name="uiMainWindow" x:Name="uiMainWindow"
Title="编辑课程" Height="500" Width="600" WindowStyle="ToolWindow" Loaded="uiMainWindow_Loaded" Closed="uiMainWindow_Closed"> Title="编辑课程" Height="500" Width="600" WindowStyle="ToolWindow" Loaded="uiMainWindow_Loaded" Closed="uiMainWindow_Closed">
<Grid> <Grid>
@ -27,11 +27,11 @@
<TextBlock Text="课程颜色" FontWeight="Bold" Padding="5" Margin="0,10,0,0"/> <TextBlock Text="课程颜色" FontWeight="Bold" Padding="5" Margin="0,10,0,0"/>
<Border ToolTip="单击改变颜色" Width="200" HorizontalAlignment="Left" BorderBrush="Black" BorderThickness="1" Cursor="Hand" Margin="0,5,0,0"> <Border ToolTip="单击改变颜色" Width="200" HorizontalAlignment="Left" BorderBrush="Black" BorderThickness="1" Cursor="Hand" Margin="0,5,0,0">
<Border.Background> <Border.Background>
<SolidColorBrush Color="{Binding Background, Mode=TwoWay}"/> <SolidColorBrush Color="{Binding Color.Background, Mode=TwoWay}"/>
</Border.Background> </Border.Background>
<TextBlock Text="示例颜色" Margin="5"> <TextBlock Text="示例颜色" Margin="5">
<TextBlock.Foreground> <TextBlock.Foreground>
<SolidColorBrush Color="{Binding Foreground, Mode=TwoWay}"/> <SolidColorBrush Color="{Binding Color.Foreground, Mode=TwoWay}"/>
</TextBlock.Foreground> </TextBlock.Foreground>
</TextBlock> </TextBlock>
</Border> </Border>
@ -45,7 +45,7 @@
<ListBox x:Name="uiSchedulesList" ItemsSource="{Binding Schedules, Mode=OneWay}" Margin="10" MouseDoubleClick="uiSchedulesList_MouseDoubleClick"> <ListBox x:Name="uiSchedulesList" ItemsSource="{Binding Schedules, Mode=OneWay}" Margin="10" MouseDoubleClick="uiSchedulesList_MouseDoubleClick">
<ListBox.ItemTemplate> <ListBox.ItemTemplate>
<DataTemplate> <DataTemplate>
<Grid d:DataContext="{d:DesignInstance userdata:Schedule}"> <Grid d:DataContext="{d:DesignInstance uidata:Schedule}">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/> <ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>

View File

@ -21,7 +21,7 @@ namespace HFUTCourseSimulation.Dialog {
InitializeComponent(); InitializeComponent();
} }
public Kernel.UserData.Course CurrentCourse { get; set; } public Kernel.Data.Ui.Course CurrentCourse { get; set; }
private void uiMainWindow_Loaded(object sender, RoutedEventArgs e) { private void uiMainWindow_Loaded(object sender, RoutedEventArgs e) {
this.DataContext = CurrentCourse; this.DataContext = CurrentCourse;
@ -38,19 +38,19 @@ namespace HFUTCourseSimulation.Dialog {
private void uiCtxMenuNewSchedule_Click(object sender, RoutedEventArgs e) { private void uiCtxMenuNewSchedule_Click(object sender, RoutedEventArgs e) {
// Create new item and order user edit it // Create new item and order user edit it
var item = new Kernel.UserData.Schedule(); var item = new Kernel.Data.Storage.Schedule();
var dialog = new EditSchedule(); var dialog = new EditSchedule();
dialog.CurrentSchedule = item; dialog.CurrentSchedule = new Kernel.Data.Ui.Schedule(item);
dialog.ShowDialog(); dialog.ShowDialog();
// Then insert or append it into list // Then insert or append it into list
var idx = uiSchedulesList.SelectedIndex; var idx = uiSchedulesList.SelectedIndex;
if (idx < 0) { if (idx < 0) {
// No selection, append. // No selection, append.
CurrentCourse.Schedules.Add(item); CurrentCourse.Schedules.Add(dialog.CurrentSchedule);
} else { } else {
// Has selection, insert // Has selection, insert
CurrentCourse.Schedules.Insert(idx, item); CurrentCourse.Schedules.Insert(idx, dialog.CurrentSchedule);
} }
} }

View File

@ -4,9 +4,9 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:HFUTCourseSimulation.Dialog" xmlns:local="clr-namespace:HFUTCourseSimulation.Dialog"
xmlns:userdata="clr-namespace:HFUTCourseSimulation.Kernel.UserData" xmlns:uidata="clr-namespace:HFUTCourseSimulation.Kernel.Data.Ui"
mc:Ignorable="d" mc:Ignorable="d"
d:DataContext="{d:DesignInstance userdata:Schedule}" d:DataContext="{d:DesignInstance uidata:Schedule}"
x:Name="uiMainWindow" x:Name="uiMainWindow"
Title="编辑课程安排" Height="450" Width="600" WindowStyle="ToolWindow" Loaded="uiMainWindow_Loaded" Closed="uiMainWindow_Closed"> Title="编辑课程安排" Height="450" Width="600" WindowStyle="ToolWindow" Loaded="uiMainWindow_Loaded" Closed="uiMainWindow_Closed">
<Grid> <Grid>

View File

@ -21,7 +21,7 @@ namespace HFUTCourseSimulation.Dialog {
InitializeComponent(); InitializeComponent();
} }
public Kernel.UserData.Schedule CurrentSchedule { get; set; } public Kernel.Data.Ui.Schedule CurrentSchedule { get; set; }
private void uiMainWindow_Loaded(object sender, RoutedEventArgs e) { private void uiMainWindow_Loaded(object sender, RoutedEventArgs e) {
this.DataContext = CurrentSchedule; this.DataContext = CurrentSchedule;

View File

@ -83,10 +83,11 @@
</Compile> </Compile>
<Compile Include="General.cs" /> <Compile Include="General.cs" />
<Compile Include="ImageExport.cs" /> <Compile Include="ImageExport.cs" />
<Compile Include="Kernel\Data\Presentation.cs" />
<Compile Include="Kernel\Data\Storage.cs" />
<Compile Include="Kernel\Data\Ui.cs" />
<Compile Include="Kernel\MsgRecorder.cs" /> <Compile Include="Kernel\MsgRecorder.cs" />
<Compile Include="Kernel\OldUserData\V1.cs" /> <Compile Include="Kernel\Data\LegacyStorage\V1.cs" />
<Compile Include="Kernel\SimData.cs" />
<Compile Include="Kernel\UserData.cs" />
<Compile Include="Simulation.xaml.cs"> <Compile Include="Simulation.xaml.cs">
<DependentUpon>Simulation.xaml</DependentUpon> <DependentUpon>Simulation.xaml</DependentUpon>
</Compile> </Compile>

View File

@ -7,9 +7,9 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Media; using System.Windows.Media;
namespace HFUTCourseSimulation.Kernel.OldUserData.V1 { namespace HFUTCourseSimulation.Kernel.Data.LegacyStorage.V1 {
public class Semester { public class Semester : Storage.IFromLegacy {
public Semester() { public Semester() {
this.Courses = new List<CourseItem>(); this.Courses = new List<CourseItem>();
StartDate = DateTime.Today; StartDate = DateTime.Today;
@ -24,8 +24,8 @@ namespace HFUTCourseSimulation.Kernel.OldUserData.V1 {
[JsonProperty("Courses")] [JsonProperty("Courses")]
public List<CourseItem> Courses { get; set; } public List<CourseItem> Courses { get; set; }
public UserData.Semester ToLatest() { public Storage.Semester ToLatest() {
return new UserData.Semester() { return new Storage.Semester() {
StartDate = StartDate, StartDate = StartDate,
WeekCount = WeekCount.ToString(), WeekCount = WeekCount.ToString(),
// Other properties keep original value. // Other properties keep original value.
@ -50,12 +50,14 @@ namespace HFUTCourseSimulation.Kernel.OldUserData.V1 {
[JsonProperty("Schedule")] [JsonProperty("Schedule")]
public List<ScheduleItem> Schedule { get; set; } public List<ScheduleItem> Schedule { get; set; }
public UserData.Course ToLatest() { public Storage.Course ToLatest() {
return new UserData.Course() { return new Storage.Course() {
Name = Name, Name = Name,
Description = Description, Description = Description,
Color = new Storage.ColorPair() {
Foreground = Colors.Black, Foreground = Colors.Black,
Background = BkColor, Background = BkColor
},
Schedules = Schedule.Select((item) => item.ToLatest()).ToList() Schedules = Schedule.Select((item) => item.ToLatest()).ToList()
}; };
} }
@ -69,8 +71,8 @@ namespace HFUTCourseSimulation.Kernel.OldUserData.V1 {
[JsonProperty("Index")] [JsonProperty("Index")]
public string Index { get; set; } public string Index { get; set; }
public UserData.Schedule ToLatest() { public Storage.Schedule ToLatest() {
return new UserData.Schedule() { return new Storage.Schedule() {
Week = Week, Week = Week,
Day = Day, Day = Day,
Index = Index Index = Index

View File

@ -5,7 +5,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace HFUTCourseSimulation.Kernel.SimData { namespace HFUTCourseSimulation.Kernel.Data.Presentation {
/// <summary> /// <summary>
/// 节次的类型 /// 节次的类型

View File

@ -1,4 +1,5 @@
using Newtonsoft.Json; using HFUTCourseSimulation.Util;
using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
@ -6,9 +7,15 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Media; using System.Windows.Media;
using HFUTCourseSimulation.Util;
namespace HFUTCourseSimulation.Kernel.UserData { namespace HFUTCourseSimulation.Kernel.Data.Storage {
/// <summary>
/// 表示可以从旧版数据结构转换为最新版本的接口。
/// </summary>
public interface IFromLegacy {
Semester ToLatest();
}
/// <summary> /// <summary>
/// 学期数据 /// 学期数据
@ -66,9 +73,7 @@ namespace HFUTCourseSimulation.Kernel.UserData {
public Course() { public Course() {
Name = ""; Name = "";
Description = ""; Description = "";
var color = Util.ColorPreset.MdColors.Indigo; Color = ColorTrans.ToStorageColorPair(Util.ColorPreset.MdColors.Indigo);
Foreground = color.Foreground;
Background = color.Background;
Schedules = new List<Schedule>(); Schedules = new List<Schedule>();
} }
@ -83,17 +88,10 @@ namespace HFUTCourseSimulation.Kernel.UserData {
[JsonProperty("description")] [JsonProperty("description")]
public string Description { get; set; } public string Description { get; set; }
/// <summary> /// <summary>
/// 课程的前景色(文本) /// 课程的颜色。
/// </summary> /// </summary>
[JsonProperty("foreground")] [JsonProperty("color")]
[JsonConverter(typeof(CustomColorConverter))] public ColorPair Color { get; set; }
public Color Foreground { get; set; }
/// <summary>
/// 课程的背景色(背景)
/// </summary>
[JsonProperty("background")]
[JsonConverter(typeof(CustomColorConverter))]
public Color Background { get; set; }
/// <summary> /// <summary>
/// 课程的所有安排 /// 课程的所有安排
/// </summary> /// </summary>
@ -125,6 +123,29 @@ namespace HFUTCourseSimulation.Kernel.UserData {
public string Index { get; set; } public string Index { get; set; }
} }
/// <summary>
/// 课程颜色对,包含前景色和背景色
/// </summary>
public class ColorPair {
public ColorPair() {
Foreground = Colors.Black;
Background = Colors.White;
}
/// <summary>
/// 前景色(文本)
/// </summary>
[JsonProperty("foreground")]
[JsonConverter(typeof(CustomColorConverter))]
public Color Foreground { get; set; }
/// <summary>
/// 背景色(背景)
/// </summary>
[JsonProperty("background")]
[JsonConverter(typeof(CustomColorConverter))]
public Color Background { get; set; }
}
internal class CustomDateTimeConverter : JsonConverter<DateTime> { internal class CustomDateTimeConverter : JsonConverter<DateTime> {
private static readonly string DatetimeFormat = "yyyy-MM-dd"; private static readonly string DatetimeFormat = "yyyy-MM-dd";

View File

@ -0,0 +1,206 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
namespace HFUTCourseSimulation.Kernel.Data.Ui {
public class Semester : INotifyPropertyChanged {
public Semester(Storage.Semester rhs) {
_startDate = rhs.StartDate;
_weekCount = rhs.WeekCount;
_indexCount = rhs.IndexCount;
_breakfastAt = rhs.BreakfastAt;
_lunchAt = rhs.LunchAt;
_dinnerAt = rhs.DinnerAt;
_courses = new ObservableCollection<Course>(rhs.Courses.Select((item) => new Course(item)));
}
public Storage.Semester ToStorage() {
return new Storage.Semester() {
StartDate = _startDate,
WeekCount = _weekCount,
IndexCount = _indexCount,
BreakfastAt = _breakfastAt,
LunchAt = _lunchAt,
DinnerAt = _dinnerAt,
Courses = _courses.Select((item) => item.ToStorage()).ToList()
};
}
private DateTime _startDate;
private string _weekCount;
private string _indexCount;
private string _breakfastAt;
private string _lunchAt;
private string _dinnerAt;
private ObservableCollection<Course> _courses;
public DateTime StartDate {
get { return _startDate; }
set { _startDate = value; OnPropertyChanged(nameof(StartDate)); }
}
public string WeekCount {
get { return _weekCount; }
set { _weekCount = value; OnPropertyChanged(nameof(WeekCount)); }
}
public string IndexCount {
get { return _indexCount; }
set { _indexCount = value; OnPropertyChanged(nameof(IndexCount)); }
}
public string BreakfastAt {
get { return _breakfastAt; }
set { _breakfastAt = value; OnPropertyChanged(nameof(BreakfastAt)); }
}
public string LunchAt {
get { return _lunchAt; }
set { _lunchAt = value; OnPropertyChanged(nameof(LunchAt)); }
}
public string DinnerAt {
get { return _dinnerAt; }
set { _dinnerAt = value; OnPropertyChanged(nameof(DinnerAt)); }
}
public ObservableCollection<Course> Courses {
get { return _courses; }
set { _courses = value; OnPropertyChanged(nameof(Courses)); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name = null) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
public class Course : INotifyPropertyChanged {
public Course(Storage.Course rhs) {
_name = rhs.Name;
_description = rhs.Description;
_color = new ColorPair(rhs.Color);
_schedules = new ObservableCollection<Schedule>(rhs.Schedules.Select((item) => new Schedule(item)));
SubscribeScheduleChanges();
}
public Storage.Course ToStorage() {
return new Storage.Course() {
Name = _name,
Description = _description,
Color = _color.ToStorage(),
Schedules = _schedules.Select((item) => item.ToStorage()).ToList()
};
}
private string _name;
private string _description;
private ColorPair _color;
private ObservableCollection<Schedule> _schedules;
public string Name {
get { return _name; }
set { _name = value; OnPropertyChanged(nameof(Name)); }
}
public string Description {
get { return _description; }
set { _description = value; OnPropertyChanged(nameof(Description)); }
}
public ColorPair Color {
get { return _color; }
set { _color = value; OnPropertyChanged(nameof(Color)); }
}
public ObservableCollection<Schedule> Schedules {
get { return _schedules; }
set {
// Common codes
_schedules = value;
OnPropertyChanged(nameof(Schedule));
// We also need register a event for the change of this list,
// because showcase schedules need it.
SubscribeScheduleChanges();
}
}
public string ShowcaseSchedules => $"共计{_schedules.Count}个课程安排";
/// <summary>
/// 用于订阅Schedules集合改变的通知用于通知ShowcaseSchedules的改变。
/// </summary>
protected void SubscribeScheduleChanges() {
_schedules.CollectionChanged += (sender, e) => {
OnPropertyChanged(nameof(ShowcaseSchedules));
};
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name = null) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
public class Schedule : INotifyPropertyChanged {
public Schedule(Storage.Schedule rhs) {
_week = rhs.Week;
_day = rhs.Day;
_index = rhs.Index;
}
public Storage.Schedule ToStorage() {
return new Storage.Schedule() {
Week = _week,
Day = _day,
Index = _index
};
}
private string _week;
private string _day;
private string _index;
public string Week {
get { return _week; }
set { _week = value; OnPropertyChanged(nameof(Week)); }
}
public string Day {
get { return _day; }
set { _day = value; OnPropertyChanged(nameof(Day)); }
}
public string Index {
get { return _index; }
set { _index = value; OnPropertyChanged(nameof(Index)); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name = null) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
public class ColorPair : INotifyPropertyChanged {
public ColorPair(Storage.ColorPair rhs) {
_foreground = rhs.Foreground;
_background = rhs.Background;
}
public Storage.ColorPair ToStorage() {
return new Storage.ColorPair() {
Foreground = _foreground,
Background = _background
};
}
private Color _foreground;
private Color _background;
public Color Foreground {
get { return _foreground; }
set { _foreground = value; OnPropertyChanged(nameof(Foreground)); }
}
public Color Background {
get { return _background; }
set { _background = value; OnPropertyChanged(nameof(Background)); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name = null) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
}

View File

@ -4,9 +4,9 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:HFUTCourseSimulation" xmlns:local="clr-namespace:HFUTCourseSimulation"
xmlns:userdata="clr-namespace:HFUTCourseSimulation.Kernel.UserData" xmlns:uidata="clr-namespace:HFUTCourseSimulation.Kernel.Data.Ui"
mc:Ignorable="d" mc:Ignorable="d"
d:DataContext="{d:DesignInstance userdata:Semester}" d:DataContext="{d:DesignInstance uidata:Semester}"
Title="HFUT课表模拟" Height="600" Width="800"> Title="HFUT课表模拟" Height="600" Width="800">
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
@ -65,25 +65,25 @@
<ListBox x:Name="uiCoursesList" ItemsSource="{Binding Courses, Mode=OneWay}" Margin="10" MouseDoubleClick="uiCoursesList_MouseDoubleClick"> <ListBox x:Name="uiCoursesList" ItemsSource="{Binding Courses, Mode=OneWay}" Margin="10" MouseDoubleClick="uiCoursesList_MouseDoubleClick">
<ListBox.ItemTemplate> <ListBox.ItemTemplate>
<DataTemplate> <DataTemplate>
<Grid d:DataContext="{d:DesignInstance userdata:Course}"> <Grid d:DataContext="{d:DesignInstance uidata:Course}">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/> <ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Border Grid.Column="0" BorderBrush="Black" BorderThickness="1" CornerRadius="2" Margin="5" VerticalAlignment="Top"> <Border Grid.Column="0" BorderBrush="Black" BorderThickness="1" CornerRadius="2" Margin="5" VerticalAlignment="Top">
<Border.Background> <Border.Background>
<SolidColorBrush Color="{Binding Background, Mode=OneWay}"/> <SolidColorBrush Color="{Binding Color.Background, Mode=OneWay}"/>
</Border.Background> </Border.Background>
<TextBlock Text="课" Margin="5"> <TextBlock Text="课" Margin="5">
<TextBlock.Foreground> <TextBlock.Foreground>
<SolidColorBrush Color="{Binding Foreground, Mode=OneWay}"/> <SolidColorBrush Color="{Binding Color.Foreground, Mode=OneWay}"/>
</TextBlock.Foreground> </TextBlock.Foreground>
</TextBlock> </TextBlock>
</Border> </Border>
<StackPanel Orientation="Vertical" Grid.Column="1"> <StackPanel Orientation="Vertical" Grid.Column="1">
<TextBlock Text="{Binding Name, Mode=OneWay}" FontWeight="Bold"/> <TextBlock Text="{Binding Name, Mode=OneWay}" FontWeight="Bold"/>
<TextBlock Text="这是一段注释"/> <TextBlock Text="{Binding Description, Mode=OneWay}"/>
<TextBlock Text="共计N个课程安排"/> <TextBlock Text="{Binding ShowcaseSchedules, Mode=OneWay}"/>
</StackPanel> </StackPanel>
</Grid> </Grid>
</DataTemplate> </DataTemplate>

View File

@ -1,4 +1,5 @@
using HFUTCourseSimulation.Dialog; using HFUTCourseSimulation.Dialog;
using HFUTCourseSimulation.Util;
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -28,7 +29,7 @@ namespace HFUTCourseSimulation {
#region Context and Assistant Functions #region Context and Assistant Functions
private Kernel.UserData.Semester CurrentSemester { get; set; } private Kernel.Data.Ui.Semester CurrentSemester { get; set; }
private string CurrentFilePath { get; set; } private string CurrentFilePath { get; set; }
/// <summary> /// <summary>
@ -101,8 +102,14 @@ namespace HFUTCourseSimulation {
#region Menu Handlers #region Menu Handlers
private void uiMenuNew_Click(object sender, RoutedEventArgs e) { private void uiMenuNew_Click(object sender, RoutedEventArgs e) {
CurrentSemester = new Kernel.UserData.Semester(); // Create new blank semester.
var new_obj = new Kernel.Data.Storage.Semester();
// Convert into struct for Ui and clean assoc file path.
CurrentSemester = new Kernel.Data.Ui.Semester(new_obj);
CurrentFilePath = null; CurrentFilePath = null;
// Update UI and data source
UpdateUiLayout(); UpdateUiLayout();
UpdateDataSource(); UpdateDataSource();
} }
@ -115,7 +122,35 @@ namespace HFUTCourseSimulation {
// Try to read file. // Try to read file.
try { try {
using (var fs = new StreamReader(filepath, Encoding.UTF8)) { using (var fs = new StreamReader(filepath, Encoding.UTF8)) {
CurrentSemester = JsonConvert.DeserializeObject<Kernel.UserData.Semester>(fs.ReadToEnd()); // Read semester object.
var obj = JsonConvert.DeserializeObject<Kernel.Data.Storage.Semester>(fs.ReadToEnd());
// Convert into struct for Ui and add assoc file path.
CurrentSemester = new Kernel.Data.Ui.Semester(obj);
CurrentFilePath = filepath;
}
} catch (Exception ex) {
Util.Win32Dialog.Error(ex.ToString(), "打开文件时出错");
return;
}
// Update UI and data source
UpdateUiLayout();
UpdateDataSource();
}
private void OpenLegacy<T>() where T : Kernel.Data.Storage.IFromLegacy {
// Fetch file path.
var filepath = Util.Win32Dialog.OpenSemester();
if (filepath is null) return;
// Try to read file.
try {
using (var fs = new StreamReader(filepath, Encoding.UTF8)) {
// Read legacy file and convert it into latest file.
var obj = JsonConvert.DeserializeObject<T>(fs.ReadToEnd());
var latest_obj = obj.ToLatest();
// Convert into struct for Ui and add assoc file path.
CurrentSemester = new Kernel.Data.Ui.Semester(latest_obj);
CurrentFilePath = filepath; CurrentFilePath = filepath;
} }
} catch (Exception ex) { } catch (Exception ex) {
@ -129,25 +164,7 @@ namespace HFUTCourseSimulation {
} }
private void uiMenuOpenV1_Click(object sender, RoutedEventArgs e) { private void uiMenuOpenV1_Click(object sender, RoutedEventArgs e) {
// Fetch file path. OpenLegacy<Kernel.Data.LegacyStorage.V1.Semester>();
var filepath = Util.Win32Dialog.OpenSemester();
if (filepath is null) return;
// Try to read file.
try {
using (var fs = new StreamReader(filepath, Encoding.UTF8)) {
var obj = JsonConvert.DeserializeObject<Kernel.OldUserData.V1.Semester>(fs.ReadToEnd());
CurrentSemester = obj.ToLatest();
CurrentFilePath = filepath;
}
} catch (Exception ex) {
Util.Win32Dialog.Error(ex.ToString(), "打开文件时出错");
return;
}
// Update UI and data source
UpdateUiLayout();
UpdateDataSource();
} }
private void uiMenuSave_Click(object sender, RoutedEventArgs e) { private void uiMenuSave_Click(object sender, RoutedEventArgs e) {
@ -162,7 +179,7 @@ namespace HFUTCourseSimulation {
// Try to save file // Try to save file
try { try {
using (var fs = new StreamWriter(CurrentFilePath, false, Encoding.UTF8)) { using (var fs = new StreamWriter(CurrentFilePath, false, Encoding.UTF8)) {
fs.Write(JsonConvert.SerializeObject(CurrentSemester)); fs.Write(JsonConvert.SerializeObject(CurrentSemester.ToStorage()));
} }
} catch (Exception ex) { } catch (Exception ex) {
Util.Win32Dialog.Error(ex.ToString(), "保存文件时出错"); Util.Win32Dialog.Error(ex.ToString(), "保存文件时出错");
@ -184,7 +201,7 @@ namespace HFUTCourseSimulation {
// Try to save file // Try to save file
try { try {
using (var fs = new StreamWriter(CurrentFilePath, false, Encoding.UTF8)) { using (var fs = new StreamWriter(CurrentFilePath, false, Encoding.UTF8)) {
fs.Write(JsonConvert.SerializeObject(CurrentSemester)); fs.Write(JsonConvert.SerializeObject(CurrentSemester.ToStorage()));
} }
} catch (Exception ex) { } catch (Exception ex) {
Util.Win32Dialog.Error(ex.ToString(), "保存文件时出错"); Util.Win32Dialog.Error(ex.ToString(), "保存文件时出错");
@ -221,39 +238,40 @@ namespace HFUTCourseSimulation {
} }
private void uiMenuSimulator_Click(object sender, RoutedEventArgs e) { private void uiMenuSimulator_Click(object sender, RoutedEventArgs e) {
var win = new Simulation(); //var win = new Simulation();
win.ShowDialog(); //win.ShowDialog();
} }
private void uiMenuRender_Click(object sender, RoutedEventArgs e) { private void uiMenuRender_Click(object sender, RoutedEventArgs e) {
//convert data ////convert data
int weekCount; //int weekCount;
DateTime originDate; //DateTime originDate;
try { //try {
originDate = DateTime.Parse(General.GeneralSheet.StartDate); // originDate = DateTime.Parse(General.GeneralSheet.StartDate);
weekCount = General.GeneralSheet.WeekCount; // weekCount = General.GeneralSheet.WeekCount;
} catch (Exception) { //} catch (Exception) {
MessageBox.Show("周数或日期转换错误,无法输出", "错误", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK); // MessageBox.Show("周数或日期转换错误,无法输出", "错误", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK);
return; // return;
} //}
//open file ////open file
var sp = new Microsoft.Win32.SaveFileDialog(); //var sp = new Microsoft.Win32.SaveFileDialog();
sp.RestoreDirectory = true; //sp.RestoreDirectory = true;
sp.Filter = "图片文件(*.png)|*.png|所有文件(*.*)|*.*"; //sp.Filter = "图片文件(*.png)|*.png|所有文件(*.*)|*.*";
var status = sp.ShowDialog(); //var status = sp.ShowDialog();
if (!(status.HasValue && status.Value)) return; //if (!(status.HasValue && status.Value)) return;
var getFile = sp.FileName; //var getFile = sp.FileName;
//export ////export
var res = ImageExport.Export(originDate, weekCount, getFile); //var res = ImageExport.Export(originDate, weekCount, getFile);
if (!res) MessageBox.Show("当前课程安排存在冲突,请通过实时预览消除所有错误后才能使用此功能来导出为图片", "错误", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK); //if (!res) MessageBox.Show("当前课程安排存在冲突,请通过实时预览消除所有错误后才能使用此功能来导出为图片", "错误", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK);
else MessageBox.Show("导出成功", "关于", MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK); //else MessageBox.Show("导出成功", "关于", MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK);
} }
private void uiMenuAbout_Click(object sender, RoutedEventArgs e) { private void uiMenuAbout_Click(object sender, RoutedEventArgs e) {
MessageBox.Show("本程序为开源程序。" + Environment.NewLine + "开源地址https://gitee.com/yyc12345/HFUTCourseSimulation" + Environment.NewLine + Win32Dialog.Info(@"本程序为开源程序。
"本程序旨在为各位选课的同学提供一个用于查验课程冲突以及查看课表的功能。如果您想参与开发提交PullRequest即可欢迎您的加入。", "关于", MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK); 开源地址https://gitee.com/yyc12345/HFUTCourseSimulation
本程序旨在为各位选课的同学提供一个用于查验课程冲突以及查看课表的功能。如果您想参与开发提交PullRequest即可欢迎您的加入。", "关于");
} }
#endregion #endregion
@ -267,19 +285,19 @@ namespace HFUTCourseSimulation {
private void uiCtxMenuNewCourse_Click(object sender, RoutedEventArgs e) { private void uiCtxMenuNewCourse_Click(object sender, RoutedEventArgs e) {
// Create new item and order user edit it // Create new item and order user edit it
var item = new Kernel.UserData.Course(); var item = new Kernel.Data.Storage.Course();
var dialog = new Dialog.EditCourse(); var dialog = new Dialog.EditCourse();
dialog.CurrentCourse = item; dialog.CurrentCourse = new Kernel.Data.Ui.Course(item);
dialog.ShowDialog(); dialog.ShowDialog();
// Then insert or append it into list // Then insert or append it into list
var idx = uiCoursesList.SelectedIndex; var idx = uiCoursesList.SelectedIndex;
if (idx < 0) { if (idx < 0) {
// No selection, append. // No selection, append.
CurrentSemester.Courses.Add(item); CurrentSemester.Courses.Add(dialog.CurrentCourse);
} else { } else {
// Has selection, insert // Has selection, insert
CurrentSemester.Courses.Insert(idx, item); CurrentSemester.Courses.Insert(idx, dialog.CurrentCourse);
} }
} }

View File

@ -7,6 +7,9 @@ using System.Threading.Tasks;
using WpfColor = System.Windows.Media.Color; using WpfColor = System.Windows.Media.Color;
using WinformColor = System.Drawing.Color; using WinformColor = System.Drawing.Color;
using StandardColorPair = HFUTCourseSimulation.Util.ColorPair;
using StorageColorPair = HFUTCourseSimulation.Kernel.Data.Storage.ColorPair;
namespace HFUTCourseSimulation.Util { namespace HFUTCourseSimulation.Util {
public static class ColorTrans { public static class ColorTrans {
@ -49,5 +52,23 @@ namespace HFUTCourseSimulation.Util {
#endregion #endregion
#region Color Pair
public static StandardColorPair ToStandardColorPair(StorageColorPair cp) {
return new StandardColorPair() {
Background = cp.Background,
Foreground = cp.Foreground
};
}
public static StorageColorPair ToStorageColorPair(StandardColorPair cp) {
return new StorageColorPair() {
Background = cp.Background,
Foreground = cp.Foreground
};
}
#endregion
} }
} }

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Media;
namespace HFUTCourseSimulation.Util { namespace HFUTCourseSimulation.Util {
public static class Win32Dialog { public static class Win32Dialog {
@ -48,6 +49,17 @@ namespace HFUTCourseSimulation.Util {
else return sp.FileName; else return sp.FileName;
} }
/// <summary>
/// 颜色选择框
/// </summary>
/// <returns>如果用户选择颜色并点击了确定则返回用户选择的颜色否则返回null</returns>
public static Color? PickColor() {
var picker = new System.Windows.Forms.ColorDialog();
var rv = picker.ShowDialog();
if (rv != System.Windows.Forms.DialogResult.OK) return null;
else return ColorTrans.ToWpfColor(picker.Color);
}
/// <summary> /// <summary>
/// 显示一个经典的Windows错误对话框 /// 显示一个经典的Windows错误对话框
/// </summary> /// </summary>