group and subgroup adding/editing, services added

This commit is contained in:
2023-03-26 23:01:58 +02:00
Unverified
parent 3cc4ea5b4b
commit 6e34ed1ee7
70 changed files with 2310 additions and 853 deletions

View File

@@ -11,10 +11,23 @@ namespace TimetableDesigner.Core
#region PROPERTIES
public string Name { get; set; }
public string Description { get; set; }
public Teacher Teacher { get; set; }
public Subgroup Subgroup { get; set; }
public Classroom Classroom { get; set; }
public Teacher? Teacher { get; set; }
public IGroup? Group { get; set; }
public Classroom? Classroom { get; set; }
#endregion
#region CONSTRUCTORS
public Class()
{
Name = string.Empty;
Teacher = null;
Group = null;
Classroom = null;
}
#endregion
}

View File

@@ -6,15 +6,27 @@ using System.Threading.Tasks;
namespace TimetableDesigner.Core
{
public class Group
public class Group : IGroup
{
#region PROPERTIES
public string Name { get; set; }
public string Description { get; set; }
public Subgroup MainSubgroup { get; set; }
public ICollection<Subgroup> AssignedSubgroups { get; set; }
#endregion
#region CONSTRUCTORS
public Group()
{
Name = string.Empty;
Description = string.Empty;
AssignedSubgroups = new HashSet<Subgroup>();
}
#endregion
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TimetableDesigner.Core
{
public interface IGroup
{
#region PROPERTIES
string Name { get; }
#endregion
}
}

View File

@@ -33,8 +33,10 @@ namespace TimetableDesigner.Core
Author = string.Empty;
Description = string.Empty;
TimetableTemplate = new TimetableTemplate();
Classrooms = new List<Classroom>();
Teachers = new List<Teacher>();
Classrooms = new HashSet<Classroom>();
Teachers = new HashSet<Teacher>();
Groups = new HashSet<Group>();
Subgroups = new HashSet<Subgroup>();
}
#endregion

View File

@@ -6,12 +6,22 @@ using System.Threading.Tasks;
namespace TimetableDesigner.Core
{
public class Subgroup
public class Subgroup : IGroup
{
#region PROPERTIES
public string Name { get; set; }
public string Description { get; set; }
#endregion
#region CONSTRUCTORS
public Subgroup()
{
Name = string.Empty;
}
#endregion
}

View File

@@ -33,29 +33,29 @@ namespace TimetableDesigner.Core
#region PUBLIC METHODS
internal TimetableSpansCollision CheckCollision(TimetableSpan slot)
internal TimetableSpanCollision CheckCollision(TimetableSpan slot)
{
if (slot.To <= this.From)
{
return TimetableSpansCollision.CheckedSlotBefore;
return TimetableSpanCollision.CheckedSlotBefore;
}
else if (this.To <= slot.From)
{
return TimetableSpansCollision.CheckedSlotAfter;
return TimetableSpanCollision.CheckedSlotAfter;
}
else
{
if (this.From < slot.From && slot.To < this.To)
{
return TimetableSpansCollision.CheckedSlotIn;
return TimetableSpanCollision.CheckedSlotIn;
}
else if (this.From < slot.From && slot.From < this.To && this.To < slot.To)
{
return TimetableSpansCollision.CheckedSlotFromIn;
return TimetableSpanCollision.CheckedSlotFromIn;
}
else if (slot.From < this.From && this.From < slot.To && slot.To < this.To)
{
return TimetableSpansCollision.CheckedSlotToIn;
return TimetableSpanCollision.CheckedSlotToIn;
}
else
{

View File

@@ -49,8 +49,8 @@ namespace TimetableDesigner.Core
{
switch (item.CheckCollision(_list.ElementAt(i)))
{
case TimetableSpansCollision.CheckedSlotBefore: i++; break;
case TimetableSpansCollision.CheckedSlotAfter: done ^= true; break;
case TimetableSpanCollision.CheckedSlotBefore: i++; break;
case TimetableSpanCollision.CheckedSlotAfter: done ^= true; break;
default: throw new ArgumentException("Slot collide with another slot");
}
}

View File

@@ -6,7 +6,7 @@ using System.Threading.Tasks;
namespace TimetableDesigner.Core
{
internal enum TimetableSpansCollision
internal enum TimetableSpanCollision
{
CheckedSlotBefore,
CheckedSlotAfter,

View File

@@ -7,7 +7,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TimetableDesigner.Customs.Collections
namespace TimetableDesigner.Customs
{
public class ObservableDictionary<TKey, TValue> : ObservableCollection<ObservableKeyValuePair<TKey, TValue>>, IDictionary<TKey, TValue>
{
@@ -59,7 +59,7 @@ namespace TimetableDesigner.Customs.Collections
{
foreach (KeyValuePair<TKey, TValue> pair in dictionary)
{
this.Add(pair);
Add(pair);
}
}

View File

@@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TimetableDesigner.Customs.Collections
namespace TimetableDesigner.Customs
{
public class ObservableKeyValuePair<TKey, TValue> : INotifyPropertyChanged
{

View File

@@ -5,11 +5,11 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TimetableDesigner.ViewModels.Base
namespace TimetableDesigner.Customs
{
public abstract class BaseViewModel : INotifyPropertyChanged
public class ObservableObject : INotifyPropertyChanged
{
#region PROTECTED METHODS
#region PRIVATE METHODS
protected void NotifyPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

View File

@@ -1,33 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Versioning;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using TimetableDesigner.MessageBox.Properties;
namespace TimetableDesigner.MessageBox
{
public static class MessageBoxService
{
#region PUBLIC METHODS
public static void ShowError(string message) => System.Windows.MessageBox.Show(message, Resources.Error, MessageBoxButton.OK, MessageBoxImage.Error);
public static MessageBoxYesNoCancelResult ShowYesNoCancelQuestion(string message)
{
MessageBoxResult result = System.Windows.MessageBox.Show(message, Resources.Error, MessageBoxButton.YesNoCancel, MessageBoxImage.Question);
switch (result)
{
case MessageBoxResult.Yes: return MessageBoxYesNoCancelResult.Yes;
case MessageBoxResult.No: return MessageBoxYesNoCancelResult.No;
case MessageBoxResult.Cancel: return MessageBoxYesNoCancelResult.Cancel;
default: return MessageBoxYesNoCancelResult.None;
}
}
#endregion
}
}

View File

@@ -1,81 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace TimetableDesigner.MessageBox.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TimetableDesigner.MessageBox.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Error.
/// </summary>
internal static string Error {
get {
return ResourceManager.GetString("Error", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Question.
/// </summary>
internal static string Question {
get {
return ResourceManager.GetString("Question", resourceCulture);
}
}
}
}

View File

@@ -1,126 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Error" xml:space="preserve">
<value>Error</value>
</data>
<data name="Question" xml:space="preserve">
<value>Question</value>
</data>
</root>

View File

@@ -1,24 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@@ -9,9 +9,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TimetableDesigner.Core", "T
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TimetableDesigner.Tests", "TimetableDesigner.Tests\TimetableDesigner.Tests.csproj", "{A9B4DB89-A007-472A-9C80-B6340458AC1B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TimetableDesigner.MessageBox", "TimetableDesigner.MessageBox\TimetableDesigner.MessageBox.csproj", "{95992646-6D81-4FF4-885E-8F0BE2312D54}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TimetableDesigner.Customs", "TimetableDesigner.Customs\TimetableDesigner.Customs.csproj", "{BCA4CD04-FD49-4C28-9743-F4F6C1888E7E}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TimetableDesigner.Customs", "TimetableDesigner.Customs\TimetableDesigner.Customs.csproj", "{BCA4CD04-FD49-4C28-9743-F4F6C1888E7E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -45,14 +43,6 @@ Global
{A9B4DB89-A007-472A-9C80-B6340458AC1B}.Release|Any CPU.Build.0 = Release|Any CPU
{A9B4DB89-A007-472A-9C80-B6340458AC1B}.Release|x64.ActiveCfg = Release|Any CPU
{A9B4DB89-A007-472A-9C80-B6340458AC1B}.Release|x64.Build.0 = Release|Any CPU
{95992646-6D81-4FF4-885E-8F0BE2312D54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{95992646-6D81-4FF4-885E-8F0BE2312D54}.Debug|Any CPU.Build.0 = Debug|Any CPU
{95992646-6D81-4FF4-885E-8F0BE2312D54}.Debug|x64.ActiveCfg = Debug|Any CPU
{95992646-6D81-4FF4-885E-8F0BE2312D54}.Debug|x64.Build.0 = Debug|Any CPU
{95992646-6D81-4FF4-885E-8F0BE2312D54}.Release|Any CPU.ActiveCfg = Release|Any CPU
{95992646-6D81-4FF4-885E-8F0BE2312D54}.Release|Any CPU.Build.0 = Release|Any CPU
{95992646-6D81-4FF4-885E-8F0BE2312D54}.Release|x64.ActiveCfg = Release|Any CPU
{95992646-6D81-4FF4-885E-8F0BE2312D54}.Release|x64.Build.0 = Release|Any CPU
{BCA4CD04-FD49-4C28-9743-F4F6C1888E7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BCA4CD04-FD49-4C28-9743-F4F6C1888E7E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BCA4CD04-FD49-4C28-9743-F4F6C1888E7E}.Debug|x64.ActiveCfg = Debug|Any CPU

View File

@@ -1,10 +1,15 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using TimetableDesigner.Services;
using TimetableDesigner.Services.MessageBox;
using TimetableDesigner.Services.Project;
using TimetableDesigner.Services.TabNavigation;
namespace TimetableDesigner
{
@@ -12,6 +17,9 @@ namespace TimetableDesigner
{
public App()
{
ServiceProvider.Instance.AddService<IMessageBoxService>(new MessageBoxService());
ServiceProvider.Instance.AddService<ITabNavigationService>(new TabNavigationService());
ServiceProvider.Instance.AddService<IProjectService>(new ProjectService());
}
}
}

View File

@@ -0,0 +1,34 @@
<UserControl x:Class="TimetableDesigner.Controls.TimetableEditorControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:TimetableDesigner.Controls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ItemsControl Grid.Column="0" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=_projectService.ProjectViewModel}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Grid.Column="0"
Rows="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=_projectService.ProjectViewModel.TimetableTemplate.Slots.Count, Converter={StaticResource IntegerAddConstantConverter}, ConverterParameter=1}"
Columns="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=_projectService.ProjectViewModel.TimetableTemplate.Days.Count, Converter={StaticResource IntegerAddConstantConverter}, ConverterParameter=1}"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ScrollViewer Grid.Column="1">
<StackPanel>
</StackPanel>
</ScrollViewer>
</Grid>
</UserControl>

View File

@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using TimetableDesigner.Services;
using TimetableDesigner.Services.Project;
using TimetableDesigner.ViewModels.Models;
namespace TimetableDesigner.Controls
{
public partial class TimetableEditorControl : UserControl
{
#region FIELDS
private IProjectService _projectService;
#endregion
#region PROPERTIES
public IGroupViewModel Group
{
get => (IGroupViewModel)GetValue(GroupProperty);
set => SetValue(GroupProperty, value);
}
public static readonly DependencyProperty GroupProperty = DependencyProperty.Register("Group", typeof(IGroupViewModel), typeof(TimetableEditorControl));
#endregion
#region CONSTRUCTORS
public TimetableEditorControl()
{
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
InitializeComponent();
}
#endregion
}
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
namespace TimetableDesigner.Converters
{
public class IntegerAddConstantConverter : IValueConverter
{
#region PUBLIC METHODS
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => (int)value + (int)parameter;
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => (int)value - (int)parameter;
#endregion
}
}

View File

@@ -8,7 +8,7 @@ using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using TimetableDesigner.ViewModels;
using TimetableDesigner.ViewModels.Base;
using TimetableDesigner.ViewModels.Views;
using TimetableDesigner.Views;
namespace TimetableDesigner.Converters
@@ -20,10 +20,11 @@ namespace TimetableDesigner.Converters
private static readonly Dictionary<Type, Type> _viewModelViewPairs = new Dictionary<Type, Type>
{
{ typeof(MainViewModel), typeof(MainWindow) },
{ typeof(WelcomeTabViewModel), typeof(WelcomeTabView) },
{ typeof(ProjectSettingsTabViewModel), typeof(ProjectSettingsTabView) },
{ typeof(ClassroomEditTabViewModel), typeof(ClassroomEditTabView) },
{ typeof(TeacherEditTabViewModel), typeof(TeacherEditTabView) },
{ typeof(WelcomeViewModel), typeof(WelcomeView) },
{ typeof(ProjectSettingsViewModel), typeof(ProjectSettingsView) },
{ typeof(ClassroomEditViewModel), typeof(ClassroomEditView) },
{ typeof(TeacherEditViewModel), typeof(TeacherEditView) },
{ typeof(GroupEditViewModel), typeof(GroupEditView) },
};
#endregion
@@ -34,7 +35,7 @@ namespace TimetableDesigner.Converters
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
BaseViewModel? viewModel = value as BaseViewModel;
BaseViewViewModel? viewModel = value as BaseViewViewModel;
if (viewModel is not null)
{
Type view = _viewModelViewPairs[viewModel.GetType()];

View File

@@ -87,6 +87,24 @@ namespace TimetableDesigner.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Basics.
/// </summary>
public static string ClassroomEdit_Groups_Basics {
get {
return ResourceManager.GetString("ClassroomEdit.Groups.Basics", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Capacity.
/// </summary>
public static string ClassroomEdit_Groups_Capacity {
get {
return ResourceManager.GetString("ClassroomEdit.Groups.Capacity", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Name.
/// </summary>
@@ -105,6 +123,15 @@ namespace TimetableDesigner.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to New group.
/// </summary>
public static string Global_DefaultGroupName {
get {
return ResourceManager.GetString("Global.DefaultGroupName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to New project.
/// </summary>
@@ -132,6 +159,78 @@ namespace TimetableDesigner.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Delete.
/// </summary>
public static string GroupEdit_DeleteSubgroup {
get {
return ResourceManager.GetString("GroupEdit.DeleteSubgroup", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Description.
/// </summary>
public static string GroupEdit_Description {
get {
return ResourceManager.GetString("GroupEdit.Description", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Basics.
/// </summary>
public static string GroupEdit_Groups_Basics {
get {
return ResourceManager.GetString("GroupEdit.Groups.Basics", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Subgroups.
/// </summary>
public static string GroupEdit_Groups_Subgroups {
get {
return ResourceManager.GetString("GroupEdit.Groups.Subgroups", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Are you sure you want to delete this subgroup. This operation is irreversible. Subgroup will be unassigned for all groups..
/// </summary>
public static string GroupEdit_Message_SubgroupDelete {
get {
return ResourceManager.GetString("GroupEdit.Message.SubgroupDelete", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Name.
/// </summary>
public static string GroupEdit_Name {
get {
return ResourceManager.GetString("GroupEdit.Name", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to New subgroup name.
/// </summary>
public static string GroupEdit_NewSubgroupLabel {
get {
return ResourceManager.GetString("GroupEdit.NewSubgroupLabel", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Subgroups.
/// </summary>
public static string GroupEdit_Subgroups {
get {
return ResourceManager.GetString("GroupEdit.Subgroups", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Project is loaded. Do you want to save?.
/// </summary>
@@ -141,6 +240,42 @@ namespace TimetableDesigner.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Export.
/// </summary>
public static string Main_Ribbon_Export {
get {
return ResourceManager.GetString("Main.Ribbon.Export", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Timetable.
/// </summary>
public static string Main_Ribbon_Export_Timetable {
get {
return ResourceManager.GetString("Main.Ribbon.Export.Timetable", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to PDF.
/// </summary>
public static string Main_Ribbon_Export_Timetable_PDF {
get {
return ResourceManager.GetString("Main.Ribbon.Export.Timetable.PDF", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to XLS.
/// </summary>
public static string Main_Ribbon_Export_Timetable_XLS {
get {
return ResourceManager.GetString("Main.Ribbon.Export.Timetable.XLS", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to File.
/// </summary>
@@ -222,6 +357,42 @@ namespace TimetableDesigner.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Import.
/// </summary>
public static string Main_Ribbon_Project_Import {
get {
return ResourceManager.GetString("Main.Ribbon.Project.Import", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Import classrooms.
/// </summary>
public static string Main_Ribbon_Project_Import_ImportClassrooms {
get {
return ResourceManager.GetString("Main.Ribbon.Project.Import.ImportClassrooms", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Import groups.
/// </summary>
public static string Main_Ribbon_Project_Import_ImportGroups {
get {
return ResourceManager.GetString("Main.Ribbon.Project.Import.ImportGroups", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Import teachers.
/// </summary>
public static string Main_Ribbon_Project_Import_ImportTeachers {
get {
return ResourceManager.GetString("Main.Ribbon.Project.Import.ImportTeachers", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to New.
/// </summary>
@@ -330,6 +501,33 @@ namespace TimetableDesigner.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Groups.
/// </summary>
public static string Main_Treeview_Groups {
get {
return ResourceManager.GetString("Main.Treeview.Groups", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Edit group.
/// </summary>
public static string Main_Treeview_Groups_ContextMenu_Edit {
get {
return ResourceManager.GetString("Main.Treeview.Groups.ContextMenu.Edit", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Are you sure you want to delete this subgroup. This operation is irreversible. Subgroup will be unassigned for all groups..
/// </summary>
public static string Main_Treeview_Subgroups_Message_Remove {
get {
return ResourceManager.GetString("Main.Treeview.Subgroups.Message.Remove", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Teachers.
/// </summary>
@@ -357,6 +555,15 @@ namespace TimetableDesigner.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Question.
/// </summary>
public static string MessageBox_Question {
get {
return ResourceManager.GetString("MessageBox.Question", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Author.
/// </summary>
@@ -447,6 +654,15 @@ namespace TimetableDesigner.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Group editing.
/// </summary>
public static string Tabs_GroupEdit {
get {
return ResourceManager.GetString("Tabs.GroupEdit", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Project settings.
/// </summary>
@@ -475,11 +691,11 @@ namespace TimetableDesigner.Properties {
}
/// <summary>
/// Looks up a localized string similar to Availability hours.
/// Looks up a localized string similar to Days.
/// </summary>
public static string TeacherEdit_AvailabilityHours {
public static string TeacherEdit_Days {
get {
return ResourceManager.GetString("TeacherEdit.AvailabilityHours", resourceCulture);
return ResourceManager.GetString("TeacherEdit.Days", resourceCulture);
}
}
@@ -492,6 +708,33 @@ namespace TimetableDesigner.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Availability hours.
/// </summary>
public static string TeacherEdit_Groups_AvailabilityHours {
get {
return ResourceManager.GetString("TeacherEdit.Groups.AvailabilityHours", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Basics.
/// </summary>
public static string TeacherEdit_Groups_Basics {
get {
return ResourceManager.GetString("TeacherEdit.Groups.Basics", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Hours.
/// </summary>
public static string TeacherEdit_Hours {
get {
return ResourceManager.GetString("TeacherEdit.Hours", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &quot;From&quot; value is higher or equal to &quot;To&quot; value.
/// </summary>

View File

@@ -126,12 +126,21 @@
<data name="ClassroomEdit.Description" xml:space="preserve">
<value>Description</value>
</data>
<data name="ClassroomEdit.Groups.Basics" xml:space="preserve">
<value>Basics</value>
</data>
<data name="ClassroomEdit.Groups.Capacity" xml:space="preserve">
<value>Capacity</value>
</data>
<data name="ClassroomEdit.Name" xml:space="preserve">
<value>Name</value>
</data>
<data name="Global.DefaultClassroomName" xml:space="preserve">
<value>New classroom</value>
</data>
<data name="Global.DefaultGroupName" xml:space="preserve">
<value>New group</value>
</data>
<data name="Global.DefaultProjectName" xml:space="preserve">
<value>New project</value>
</data>
@@ -141,9 +150,45 @@
<data name="Global.NoProjectLoadedTitle" xml:space="preserve">
<value>no project loaded</value>
</data>
<data name="GroupEdit.DeleteSubgroup" xml:space="preserve">
<value>Delete</value>
</data>
<data name="GroupEdit.Description" xml:space="preserve">
<value>Description</value>
</data>
<data name="GroupEdit.Groups.Basics" xml:space="preserve">
<value>Basics</value>
</data>
<data name="GroupEdit.Groups.Subgroups" xml:space="preserve">
<value>Subgroups</value>
</data>
<data name="GroupEdit.Message.SubgroupDelete" xml:space="preserve">
<value>Are you sure you want to delete this subgroup. This operation is irreversible. Subgroup will be unassigned for all groups.</value>
</data>
<data name="GroupEdit.Name" xml:space="preserve">
<value>Name</value>
</data>
<data name="GroupEdit.NewSubgroupLabel" xml:space="preserve">
<value>New subgroup name</value>
</data>
<data name="GroupEdit.Subgroups" xml:space="preserve">
<value>Subgroups</value>
</data>
<data name="Main.Message.SaveCurrentProject" xml:space="preserve">
<value>Project is loaded. Do you want to save?</value>
</data>
<data name="Main.Ribbon.Export" xml:space="preserve">
<value>Export</value>
</data>
<data name="Main.Ribbon.Export.Timetable" xml:space="preserve">
<value>Timetable</value>
</data>
<data name="Main.Ribbon.Export.Timetable.PDF" xml:space="preserve">
<value>PDF</value>
</data>
<data name="Main.Ribbon.Export.Timetable.XLS" xml:space="preserve">
<value>XLS</value>
</data>
<data name="Main.Ribbon.File" xml:space="preserve">
<value>File</value>
</data>
@@ -171,6 +216,18 @@
<data name="Main.Ribbon.Project" xml:space="preserve">
<value>Project</value>
</data>
<data name="Main.Ribbon.Project.Import" xml:space="preserve">
<value>Import</value>
</data>
<data name="Main.Ribbon.Project.Import.ImportClassrooms" xml:space="preserve">
<value>Import classrooms</value>
</data>
<data name="Main.Ribbon.Project.Import.ImportGroups" xml:space="preserve">
<value>Import groups</value>
</data>
<data name="Main.Ribbon.Project.Import.ImportTeachers" xml:space="preserve">
<value>Import teachers</value>
</data>
<data name="Main.Ribbon.Project.New" xml:space="preserve">
<value>New</value>
</data>
@@ -207,6 +264,15 @@
<data name="Main.Treeview.ContextMenu.Remove" xml:space="preserve">
<value>Remove</value>
</data>
<data name="Main.Treeview.Groups" xml:space="preserve">
<value>Groups</value>
</data>
<data name="Main.Treeview.Groups.ContextMenu.Edit" xml:space="preserve">
<value>Edit group</value>
</data>
<data name="Main.Treeview.Subgroups.Message.Remove" xml:space="preserve">
<value>Are you sure you want to delete this subgroup. This operation is irreversible. Subgroup will be unassigned for all groups.</value>
</data>
<data name="Main.Treeview.Teachers" xml:space="preserve">
<value>Teachers</value>
</data>
@@ -216,6 +282,9 @@
<data name="MessageBox.Error" xml:space="preserve">
<value>Error</value>
</data>
<data name="MessageBox.Question" xml:space="preserve">
<value>Question</value>
</data>
<data name="ProjectSettings.Author" xml:space="preserve">
<value>Author</value>
</data>
@@ -246,6 +315,9 @@
<data name="Tabs.ClassroomEdit" xml:space="preserve">
<value>Classroom editing</value>
</data>
<data name="Tabs.GroupEdit" xml:space="preserve">
<value>Group editing</value>
</data>
<data name="Tabs.ProjectSettings" xml:space="preserve">
<value>Project settings</value>
</data>
@@ -255,12 +327,21 @@
<data name="Tabs.Welcome" xml:space="preserve">
<value>Welcome</value>
</data>
<data name="TeacherEdit.AvailabilityHours" xml:space="preserve">
<value>Availability hours</value>
<data name="TeacherEdit.Days" xml:space="preserve">
<value>Days</value>
</data>
<data name="TeacherEdit.Description" xml:space="preserve">
<value>Description</value>
</data>
<data name="TeacherEdit.Groups.AvailabilityHours" xml:space="preserve">
<value>Availability hours</value>
</data>
<data name="TeacherEdit.Groups.Basics" xml:space="preserve">
<value>Basics</value>
</data>
<data name="TeacherEdit.Hours" xml:space="preserve">
<value>Hours</value>
</data>
<data name="TeacherEdit.Message.FromHigherThanTo" xml:space="preserve">
<value>"From" value is higher or equal to "To" value</value>
</data>

View File

@@ -4,4 +4,5 @@
<c:ViewModelToViewConverter x:Key="ViewModelToViewConverter"/>
<c:IsNullToVisibilityConverter x:Key="IsNullToVisibilityConverter"/>
<c:IsNotNullToBooleanConverter x:Key="IsNotNullToBooleanConverter"/>
<c:IntegerAddConstantConverter x:Key="IntegerAddConstantConverter"/>
</ResourceDictionary>

View File

@@ -16,4 +16,6 @@
<BitmapImage x:Key="SaveAsImage" UriSource="Images/SaveAs.png"/>
<BitmapImage x:Key="NewImage" UriSource="Images/New.png"/>
<BitmapImage x:Key="RightArrowImage" UriSource="Images/RightArrow.png"/>
<BitmapImage x:Key="GroupImage" UriSource="Images/Group.png"/>
<BitmapImage x:Key="GroupAddImage" UriSource="Images/GroupAdd.png"/>
</ResourceDictionary>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TimetableDesigner.Services
{
public interface IService
{
}
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TimetableDesigner.Services.MessageBox
{
public interface IMessageBoxService : IService
{
#region METHODS
void ShowError(string message);
void ShowError(string message, string title);
MessageBoxQuestionResult ShowQuestion(string message, bool hideCancelButton = false);
MessageBoxQuestionResult ShowQuestion(string message, string title, bool hideCancelButton = false);
#endregion
}
}

View File

@@ -4,13 +4,12 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TimetableDesigner.MessageBox
namespace TimetableDesigner.Services.MessageBox
{
public enum MessageBoxYesNoCancelResult
public enum MessageBoxQuestionResult
{
Yes,
No,
Cancel,
None
Cancel
}
}

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
using TimetableDesigner.Properties;
namespace TimetableDesigner.Services.MessageBox
{
public class MessageBoxService : IMessageBoxService
{
#region PUBLIC METHODS
public void ShowError(string message) => ShowError(message, Resources.MessageBox_Error);
public void ShowError(string message, string title) => System.Windows.Forms.MessageBox.Show(message, title, MessageBoxButtons.OK, MessageBoxIcon.Error);
public MessageBoxQuestionResult ShowQuestion(string message, bool hideCancelButton = false) => ShowQuestion(message, Resources.MessageBox_Question, hideCancelButton);
public MessageBoxQuestionResult ShowQuestion(string message, string title, bool hideCancelButton = false)
{
MessageBoxButton buttons = MessageBoxButton.YesNoCancel;
if (hideCancelButton)
{
buttons = MessageBoxButton.YesNo;
}
MessageBoxResult result = System.Windows.MessageBox.Show(message, title, buttons, MessageBoxImage.Question);
switch (result)
{
case MessageBoxResult.Yes: return MessageBoxQuestionResult.Yes;
case MessageBoxResult.No: return MessageBoxQuestionResult.No;
default: return MessageBoxQuestionResult.Cancel;
}
}
#endregion
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TimetableDesigner.ViewModels.Models;
namespace TimetableDesigner.Services.Project
{
public interface IProjectService : IService
{
#region PROPERTIES
Core.Project? Project { get; }
ProjectViewModel? ProjectViewModel { get; }
#endregion
#region METHODS
void New();
void Load(string path);
void Save(string path);
#endregion
}
}

View File

@@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TimetableDesigner.Core;
using TimetableDesigner.Customs;
using TimetableDesigner.Properties;
using TimetableDesigner.ViewModels.Models;
namespace TimetableDesigner.Services.Project
{
public class ProjectService : ObservableObject, IProjectService
{
#region FIELDS
private Core.Project? _project;
private ProjectViewModel? _projectViewModel;
#endregion
#region PROPERTIES
public Core.Project? Project
{
get => _project;
private set
{
if (_project != value)
{
_project = value;
NotifyPropertyChanged(nameof(Project));
}
}
}
public ProjectViewModel? ProjectViewModel
{
get => _projectViewModel;
private set
{
if (_projectViewModel != value)
{
_projectViewModel = value;
NotifyPropertyChanged(nameof(ProjectViewModel));
}
}
}
#endregion
#region CONSTRUCTORS
public ProjectService()
{
_project = null;
_projectViewModel = null;
}
#endregion
#region PUBLIC METHODS
public void New()
{
Project = new Core.Project()
{
Name = Resources.Global_DefaultProjectName,
};
ProjectViewModel = new ProjectViewModel(Project);
}
public void Load(string path)
{
}
public void Save(string path)
{
}
#endregion
}
}

View File

@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TimetableDesigner.Services
{
public class ServiceProvider
{
#region FIELDS
private Dictionary<Type, IService> _services;
#endregion
#region CONSTRUCTORS
public static readonly ServiceProvider Instance = new ServiceProvider();
private ServiceProvider()
{
_services = new Dictionary<Type, IService>();
}
#endregion
#region PUBLIC METHODS
public void AddService<T>(T service) where T : IService
{
_services[typeof(T)] = service;
}
public T GetService<T>() where T : IService
{
return (T)_services[typeof(T)];
}
#endregion
}
}

View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TimetableDesigner.Services.TabNavigation
{
public interface ITabNavigationService : IService, INotifyPropertyChanged
{
#region PROPERTIES
ObservableCollection<TabItem> Tabs { get; }
TabItem SelectedTab { get; }
#endregion
#region PUBLIC METHODS
void AddAndActivate(TabItem item);
void Add(TabItem item);
void InsertAndActivate(int index, TabItem item);
void Insert(int index, TabItem item);
void Close(TabItem item);
void Close(IEnumerable<TabItem> item);
void CloseAt(int index);
void CloseAt(IEnumerable<int> indexes);
void CloseAll();
void Activate(TabItem item);
#endregion
}
}

View File

@@ -0,0 +1,110 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows.Media;
using TimetableDesigner.Commands;
using TimetableDesigner.Customs;
using TimetableDesigner.ViewModels;
namespace TimetableDesigner.Services.TabNavigation
{
public class TabItem : ObservableObject
{
#region FIELDS
private ITabNavigationService _tabNavigationService;
private ImageSource _image;
private string _title;
private bool _isClosable;
private BaseViewViewModel _viewModel;
#endregion
#region PROPERTIES
public ImageSource Image
{
get => _image;
set
{
if (_image != value)
{
_image = value;
NotifyPropertyChanged(nameof(Image));
}
}
}
public string Title
{
get => _title;
set
{
if (_title != value)
{
_title = value;
NotifyPropertyChanged(nameof(Title));
}
}
}
public bool IsClosable
{
get => _isClosable;
set
{
if (_isClosable != value)
{
_isClosable = value;
NotifyPropertyChanged(nameof(IsClosable));
}
}
}
public BaseViewViewModel ViewModel
{
get => _viewModel;
set
{
if (_viewModel != value)
{
_viewModel = value;
NotifyPropertyChanged(nameof(ViewModel));
}
}
}
public ICommand CloseCommand { get; set; }
public ICommand ActivateCommand { get; set; }
#endregion
#region CONSTRUCTORS
public TabItem()
{
_tabNavigationService = ServiceProvider.Instance.GetService<ITabNavigationService>();
CloseCommand = new RelayCommand<object>(args => Close());
ActivateCommand = new RelayCommand<object>(args => Activate());
}
#endregion
#region PUBLIC METHODS
public void Close() => _tabNavigationService.Close(this);
public void Activate() => _tabNavigationService.Activate(this);
#endregion
}
}

View File

@@ -0,0 +1,142 @@
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.Controls;
using TimetableDesigner.Customs;
namespace TimetableDesigner.Services.TabNavigation
{
public class TabNavigationService : ObservableObject, ITabNavigationService
{
#region FIELDS
private TabItem _selectedTab;
#endregion
#region PROPERTIES
public ObservableCollection<TabItem> Tabs { get; private set; }
public TabItem? SelectedTab
{
get => _selectedTab;
private set
{
if (_selectedTab != value)
{
_selectedTab = value;
NotifyPropertyChanged(nameof(SelectedTab));
}
}
}
#endregion
#region CONSTRUCTORS
public TabNavigationService()
{
Tabs = new ObservableCollection<TabItem>();
SelectedTab = null;
}
#endregion
#region PUBLIC METHODS
public void AddAndActivate(TabItem item)
{
Add(item);
Activate(item);
}
public void Add(TabItem item) => Tabs.Add(item);
public void InsertAndActivate(int index, TabItem item)
{
Insert(index, item);
Activate(item);
}
public void Insert(int index, TabItem item) => Tabs.Insert(index, item);
public void Close(TabItem item) => Close(new List<TabItem>() { item });
public void Close(IEnumerable<TabItem> items)
{
TabItem selected = SelectedTab;
while (items.Contains(selected) && selected != null)
{
int nextIndex = Tabs.IndexOf(selected) + 1;
if (Tabs.Count > nextIndex)
{
selected = Tabs[nextIndex];
}
else
{
selected = null;
}
}
if (selected == null)
{
selected = SelectedTab;
while (items.Contains(selected) && selected != null)
{
int prevIndex = Tabs.IndexOf(selected) - 1;
if (prevIndex >= 0)
{
selected = Tabs[prevIndex];
}
else
{
selected = null;
}
}
}
foreach (TabItem item in items)
{
Tabs.Remove(item);
}
SelectedTab = selected;
}
public void CloseAt(int index) => CloseAt(new List<int>() { index });
public void CloseAt(IEnumerable<int> indexes)
{
List<TabItem> items = new List<TabItem>();
foreach (int index in indexes)
{
if (Tabs.Count > index)
{
items.Add(Tabs[index]);
}
}
Close(items);
}
public void CloseAll()
{
Tabs.Clear();
SelectedTab = null;
}
public void Activate(TabItem item)
{
if (Tabs.Contains(item))
{
SelectedTab = item;
}
}
#endregion
}
}

View File

@@ -8,12 +8,20 @@
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
<ItemGroup>
<Compile Remove="ViewModels\ProjectSettingsTabViewModel.cs" />
<Compile Remove="ViewModels\TeacherEditTabViewModel.cs" />
<Compile Remove="Views\ProjectSettingsTabView.xaml.cs" />
</ItemGroup>
<ItemGroup>
<None Remove="Resources\Images\Add.png" />
<None Remove="Resources\Images\Classroom.png" />
<None Remove="Resources\Images\ClassroomAdd.png" />
<None Remove="Resources\Images\Close.png" />
<None Remove="Resources\Images\CloseButtonImage.png" />
<None Remove="Resources\Images\Group.png" />
<None Remove="Resources\Images\GroupAdd.png" />
<None Remove="Resources\Images\New.png" />
<None Remove="Resources\Images\Open.png" />
<None Remove="Resources\Images\OpenRecent.png" />
@@ -27,6 +35,10 @@
<None Remove="Resources\Images\TeacherAdd.png" />
</ItemGroup>
<ItemGroup>
<Page Remove="Views\ProjectSettingsTabView.xaml" />
</ItemGroup>
<ItemGroup>
<Content Include="Resources\Images\Classroom.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
@@ -37,6 +49,12 @@
<Content Include="Resources\Images\Close.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Resources\Images\Group.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Resources\Images\GroupAdd.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Resources\Images\New.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
@@ -80,7 +98,6 @@
<ItemGroup>
<ProjectReference Include="..\TimetableDesigner.Core\TimetableDesigner.Core.csproj" />
<ProjectReference Include="..\TimetableDesigner.Customs\TimetableDesigner.Customs.csproj" />
<ProjectReference Include="..\TimetableDesigner.MessageBox\TimetableDesigner.MessageBox.csproj" />
</ItemGroup>
<ItemGroup>

View File

@@ -1,56 +0,0 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows.Media;
namespace TimetableDesigner.ViewModels.Base
{
public abstract class BaseTabViewModel : BaseViewModel
{
#region FIELDS
private ImageSource _tabImage;
private string _tabTitle;
private bool _isTabClosable;
#endregion
#region PROPERTIES
public ImageSource TabImage
{
get => _tabImage;
set
{
_tabImage = value;
NotifyPropertyChanged(nameof(TabImage));
}
}
public string TabTitle
{
get => _tabTitle;
set
{
_tabTitle = value;
NotifyPropertyChanged(nameof(TabTitle));
}
}
public bool IsTabClosable
{
get => _isTabClosable;
set
{
_isTabClosable = value;
NotifyPropertyChanged(nameof(IsTabClosable));
}
}
#endregion
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TimetableDesigner.Customs;
namespace TimetableDesigner.ViewModels
{
public abstract class BaseModelViewModel : ObservableObject
{
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TimetableDesigner.Customs;
namespace TimetableDesigner.ViewModels
{
public abstract class BaseViewViewModel : ObservableObject
{
}
}

View File

@@ -1,52 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TimetableDesigner.ViewModels.Base;
using TimetableDesigner.ViewModels.Models;
namespace TimetableDesigner.ViewModels
{
public class ClassroomEditTabViewModel : BaseTabViewModel
{
#region FIELDS
private ClassroomViewModel _classroom;
#endregion
#region PROPERTIES
public ClassroomViewModel Classroom
{
get => _classroom;
set
{
if (_classroom != value)
{
_classroom = value;
NotifyPropertyChanged(nameof(Classroom));
}
}
}
#endregion
#region CONSTRUCTORS
public ClassroomEditTabViewModel() : this(new ClassroomViewModel(new Core.Classroom()))
{ }
public ClassroomEditTabViewModel(ClassroomViewModel classroom) : base()
{
_classroom = classroom;
}
#endregion
}
}

View File

@@ -1,255 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Input;
using TimetableDesigner.Commands;
using TimetableDesigner.ViewModels.Base;
using System.Windows.Navigation;
using TimetableDesigner.Core;
using System.Windows;
using TimetableDesigner.Properties;
using TimetableDesigner.MessageBox;
using System.Reflection;
using TimetableDesigner.ViewModels.Models;
using System.Windows.Data;
namespace TimetableDesigner.ViewModels
{
class MainViewModel : BaseViewModel
{
#region FIELDS
private ProjectViewModel? _project;
private ObservableCollection<BaseTabViewModel> _tabs;
private BaseTabViewModel? _selectedTab;
#endregion
#region PROPERTIES
public string Version { get; set; }
public ICommand CloseTabCommand { get; set; }
public ICommand NewProjectCommand { get; set; }
public ICommand OpenProjectCommand { get; set; }
public ICommand ProjectSettingsCommand { get; set; }
public ICommand NewClassroomCommand { get; set; }
public ICommand EditClassroomCommand { get; set; }
public ICommand RemoveClassroomCommand { get; set; }
public ICommand NewTeacherCommand { get; set; }
public ICommand EditTeacherCommand { get; set; }
public ICommand RemoveTeacherCommand { get; set; }
public ObservableCollection<BaseTabViewModel> Tabs
{
get => _tabs;
set
{
_tabs = value;
NotifyPropertyChanged(nameof(Tabs));
}
}
public BaseTabViewModel? SelectedTab
{
get => _selectedTab;
set
{
_selectedTab = value;
NotifyPropertyChanged(nameof(SelectedTab));
}
}
public ProjectViewModel? Project
{
get => _project;
set
{
if (value != _project)
{
_project = value;
NotifyPropertyChanged(nameof(Project));
}
}
}
#endregion
#region CONSTRUCTORS
public MainViewModel()
{
Version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
CloseTabCommand = new RelayCommand<BaseTabViewModel>(CloseTab);
NewProjectCommand = new RelayCommand<object>(param => NewProject());
OpenProjectCommand = new RelayCommand<object>(param => OpenProject());
ProjectSettingsCommand = new RelayCommand<object>(param => ProjectSettings());
NewClassroomCommand = new RelayCommand<object>(param => NewClassroom());
EditClassroomCommand = new RelayCommand<ClassroomViewModel>(EditClassroom);
RemoveClassroomCommand = new RelayCommand<ClassroomViewModel>(DeleteClassroom);
NewTeacherCommand = new RelayCommand<object>(param => NewTeacher());
EditTeacherCommand = new RelayCommand<TeacherViewModel>(EditTeacher);
RemoveTeacherCommand = new RelayCommand<TeacherViewModel>(DeleteTeacher);
_tabs = new ObservableCollection<BaseTabViewModel>
{
new WelcomeTabViewModel() { TabTitle = Resources.Tabs_Welcome }
};
_selectedTab = Tabs.Last();
}
#endregion
#region PUBLIC METHODS
private void CloseTab(BaseTabViewModel tab)
{
if (SelectedTab == tab)
{
int index = Tabs.IndexOf(tab);
int before = index - 1;
int after = index + 1;
BaseTabViewModel newSelectedTab = null;
if (before >= 0)
{
newSelectedTab = Tabs[before];
}
else if (after >= 0 && after < Tabs.Count - 1)
{
newSelectedTab = Tabs[after];
}
SelectedTab = newSelectedTab;
}
Tabs.Remove(tab);
}
private void OpenProject()
{
}
private void NewProject()
{
if (Project is not null)
{
MessageBoxYesNoCancelResult result = MessageBoxService.ShowYesNoCancelQuestion(Resources.Main_Message_SaveCurrentProject);
switch (result)
{
case MessageBoxYesNoCancelResult.Yes: break;
case MessageBoxYesNoCancelResult.No: break;
default: return;
}
}
Tabs.Clear();
Project project = new Project()
{
Name = Resources.Global_DefaultProjectName,
};
Project = new ProjectViewModel(project);
ProjectSettings();
}
private void ProjectSettings()
{
if (Project is not null)
{
ProjectSettingsTabViewModel projectSettingsTabVM = new ProjectSettingsTabViewModel()
{
Project = Project,
TabTitle = Resources.Tabs_ProjectSettings,
IsTabClosable = true,
};
Tabs.Add(projectSettingsTabVM);
SelectedTab = Tabs.Last();
}
}
private void NewClassroom()
{
if (Project is not null)
{
Classroom classroom = new Classroom()
{
Name = Resources.Global_DefaultClassroomName
};
ClassroomViewModel classroomVM = new ClassroomViewModel(classroom);
Project.Classrooms.Add(classroomVM);
EditClassroom(classroomVM);
}
}
private void EditClassroom(ClassroomViewModel classroomViewModel)
{
ClassroomEditTabViewModel classroomEdit = new ClassroomEditTabViewModel(classroomViewModel)
{
TabTitle = $"{Resources.Tabs_ClassroomEdit}: {classroomViewModel.Name}",
IsTabClosable = true
};
Tabs.Add(classroomEdit);
SelectedTab = classroomEdit;
}
private void DeleteClassroom(ClassroomViewModel classroomViewModel)
{
if (Project is not null)
{
Project.Classrooms.Remove(classroomViewModel);
}
}
private void NewTeacher()
{
if (Project is not null)
{
Teacher teacher = new Teacher()
{
Name = Resources.Global_DefaultTeacherName
};
TeacherViewModel teacherVM = new TeacherViewModel(teacher);
Project.Teachers.Add(teacherVM);
EditTeacher(teacherVM);
}
}
private void EditTeacher(TeacherViewModel teacherViewModel)
{
if (Project is not null)
{
TeacherEditTabViewModel teacherEdit = new TeacherEditTabViewModel(teacherViewModel, Project.TimetableTemplate)
{
Teacher = teacherViewModel,
TabTitle = $"{Resources.Tabs_TeacherEdit}: {teacherViewModel.Name}",
IsTabClosable = true
};
Tabs.Add(teacherEdit);
SelectedTab = teacherEdit;
}
}
private void DeleteTeacher(TeacherViewModel teacherViewModel)
{
if (Project is not null)
{
Project.Teachers.Remove(teacherViewModel);
}
}
#endregion
}
}

View File

@@ -0,0 +1,107 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TimetableDesigner.Core;
using TimetableDesigner.Services;
using TimetableDesigner.Services.Project;
namespace TimetableDesigner.ViewModels.Models
{
public class ClassViewModel : BaseModelViewModel
{
#region FIELDS
private IProjectService _projectService;
private Class _class;
#endregion
#region PROPERTIES
public Class Class => _class;
public string Name
{
get => _class.Name;
set
{
if (_class.Name != value)
{
_class.Name = value;
NotifyPropertyChanged(nameof(Name));
}
}
}
public TeacherViewModel? Teacher
{
get => _projectService.ProjectViewModel?.Teachers.Where(vm => vm.Teacher == _class.Teacher).FirstOrDefault();
set
{
if (_class.Teacher != value?.Teacher)
{
_class.Teacher = value?.Teacher;
NotifyPropertyChanged(nameof(Teacher));
}
}
}
public IGroupViewModel? Group
{
get
{
if (_class.Group?.GetType() == typeof(GroupViewModel))
{
return _projectService.ProjectViewModel?.Groups.Where(vm => vm.Group == _class.Group).FirstOrDefault();
}
else if (_class.Group?.GetType() == typeof(SubgroupViewModel))
{
return _projectService.ProjectViewModel?.Subgroups.Where(vm => vm.Subgroup == _class.Group).FirstOrDefault();
}
else
{
return null;
}
}
set
{
if (_class.Group != value?.Group)
{
_class.Group = value?.Group;
NotifyPropertyChanged(nameof(Group));
}
}
}
public ClassroomViewModel? Classroom
{
get => _projectService.ProjectViewModel?.Classrooms.Where(vm => vm.Classroom == _class.Classroom).FirstOrDefault();
set
{
if (_class.Classroom != value?.Classroom)
{
_class.Classroom = value?.Classroom;
NotifyPropertyChanged(nameof(Classroom));
}
}
}
#endregion
#region CONSTRUCTORS
public ClassViewModel(Class @class)
{
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
_class = @class;
}
#endregion
}
}

View File

@@ -4,11 +4,10 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TimetableDesigner.Core;
using TimetableDesigner.ViewModels.Base;
namespace TimetableDesigner.ViewModels.Models
{
public class ClassroomViewModel : BaseViewModel
public class ClassroomViewModel : BaseModelViewModel
{
#region FIELDS

View File

@@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TimetableDesigner.Core;
using TimetableDesigner.Services;
using TimetableDesigner.Services.Project;
namespace TimetableDesigner.ViewModels.Models
{
public class GroupViewModel : BaseModelViewModel, IGroupViewModel
{
#region FIELDS
private IProjectService _projectService;
private Group _group;
#endregion
#region PROPERTIES
IGroup IGroupViewModel.Group => _group;
public Group Group => _group;
public string Name
{
get => _group.Name;
set
{
if (_group.Name != value)
{
_group.Name = value;
NotifyPropertyChanged(nameof(Name));
}
}
}
public string Description
{
get => _group.Description;
set
{
if (_group.Description != value)
{
_group.Description = value;
NotifyPropertyChanged(nameof(Description));
}
}
}
public ObservableCollection<SubgroupViewModel> AssignedSubgroups => new ObservableCollection<SubgroupViewModel>(_projectService.ProjectViewModel.Subgroups.Where(vm => Group.AssignedSubgroups.Contains(vm.Subgroup)));
#endregion
#region CONSTRUCTORS
public GroupViewModel(Group group)
{
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
_group = group;
}
#endregion
#region PUBLIC METHODS
public void AddSubgroup(SubgroupViewModel subgroup)
{
Group.AssignedSubgroups.Add(subgroup.Subgroup);
NotifyPropertyChanged(nameof(AssignedSubgroups));
}
public void RemoveSubgroup(SubgroupViewModel subgroup)
{
Group.AssignedSubgroups.Remove(subgroup.Subgroup);
NotifyPropertyChanged(nameof(AssignedSubgroups));
}
#endregion
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TimetableDesigner.Core;
namespace TimetableDesigner.ViewModels.Models
{
public interface IGroupViewModel
{
#region PROPERTIES
IGroup Group { get; }
string Name { get; }
#endregion
}
}

View File

@@ -5,11 +5,10 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TimetableDesigner.Core;
using TimetableDesigner.ViewModels.Base;
namespace TimetableDesigner.ViewModels.Models
{
public class ProjectViewModel : BaseViewModel
public class ProjectViewModel : BaseModelViewModel
{
#region FIELDS
@@ -62,6 +61,8 @@ namespace TimetableDesigner.ViewModels.Models
public TimetableTemplateViewModel TimetableTemplate { get; set; }
public ObservableCollection<ClassroomViewModel> Classrooms { get; set; }
public ObservableCollection<TeacherViewModel> Teachers { get; set; }
public ObservableCollection<GroupViewModel> Groups { get; set; }
public ObservableCollection<SubgroupViewModel> Subgroups { get; set; }
#endregion
@@ -80,6 +81,12 @@ namespace TimetableDesigner.ViewModels.Models
Teachers = new ObservableCollection<TeacherViewModel>();
Teachers.CollectionChanged += Teachers_CollectionChanged;
Groups = new ObservableCollection<GroupViewModel>();
Groups.CollectionChanged += Groups_CollectionChanged;
Subgroups = new ObservableCollection<SubgroupViewModel>();
Subgroups.CollectionChanged += Subgroups_CollectionChanged;
}
#endregion
@@ -132,6 +139,50 @@ namespace TimetableDesigner.ViewModels.Models
}
}
private void Groups_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
IList<GroupViewModel>? added = e.NewItems as IList<GroupViewModel>;
IList<GroupViewModel>? removed = e.OldItems as IList<GroupViewModel>;
if (removed is not null)
{
foreach (GroupViewModel vm in removed)
{
_project.Groups.Remove(vm.Group);
}
}
if (added is not null)
{
foreach (GroupViewModel vm in added)
{
_project.Groups.Add(vm.Group);
}
}
}
private void Subgroups_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
IList<SubgroupViewModel>? added = e.NewItems as IList<SubgroupViewModel>;
IList<SubgroupViewModel>? removed = e.OldItems as IList<SubgroupViewModel>;
if (removed is not null)
{
foreach (SubgroupViewModel vm in removed)
{
_project.Subgroups.Remove(vm.Subgroup);
}
}
if (added is not null)
{
foreach (SubgroupViewModel vm in added)
{
_project.Subgroups.Add(vm.Subgroup);
}
}
}
#endregion
}
}

View File

@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TimetableDesigner.Core;
namespace TimetableDesigner.ViewModels.Models
{
public class SubgroupViewModel : BaseModelViewModel, IGroupViewModel
{
#region FIELDS
private Subgroup _subgroup;
#endregion
#region PROPERTIES
IGroup IGroupViewModel.Group => _subgroup;
public Subgroup Subgroup => _subgroup;
public string Name
{
get => _subgroup.Name;
set
{
if (_subgroup.Name != value)
{
_subgroup.Name = value;
NotifyPropertyChanged(nameof(Name));
}
}
}
#endregion
#region CONSTRUCTORS
public SubgroupViewModel(Subgroup subgroup)
{
_subgroup = subgroup;
}
#endregion
}
}

View File

@@ -5,12 +5,11 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TimetableDesigner.Core;
using TimetableDesigner.Customs.Collections;
using TimetableDesigner.ViewModels.Base;
using TimetableDesigner.Customs;
namespace TimetableDesigner.ViewModels.Models
{
public class TeacherViewModel : BaseViewModel
public class TeacherViewModel : BaseModelViewModel
{
#region FIELDS

View File

@@ -5,11 +5,10 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TimetableDesigner.Core;
using TimetableDesigner.ViewModels.Base;
namespace TimetableDesigner.ViewModels.Models
{
public class TimetableTemplateViewModel : BaseViewModel
public class TimetableTemplateViewModel : BaseModelViewModel
{
#region FIELDS

View File

@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TimetableDesigner.Core;
using TimetableDesigner.Customs;
using TimetableDesigner.Properties;
using TimetableDesigner.Services;
using TimetableDesigner.Services.TabNavigation;
using TimetableDesigner.ViewModels.Models;
namespace TimetableDesigner.ViewModels.Views
{
public class ClassroomEditViewModel : BaseViewViewModel
{
#region FIELDS
private ClassroomViewModel _classroom;
#endregion
#region PROPERTIES
public ClassroomViewModel Classroom
{
get => _classroom;
set
{
if (_classroom != value)
{
_classroom = value;
NotifyPropertyChanged(nameof(Classroom));
}
}
}
public string Name
{
get => _classroom.Name;
set
{
if (_classroom.Name != value)
{
_classroom.Name = value;
NotifyPropertyChanged(nameof(Name));
TabItem? tab = ServiceProvider.Instance.GetService<ITabNavigationService>().Tabs.Where(tab => tab.ViewModel == this).FirstOrDefault();
if (tab != null)
{
tab.Title = $"{Resources.Tabs_ClassroomEdit}: {_classroom.Name}";
}
}
}
}
#endregion
#region CONSTRUCTORS
public ClassroomEditViewModel() : this(new ClassroomViewModel(new Classroom()))
{ }
public ClassroomEditViewModel(ClassroomViewModel classroom)
{
_classroom = classroom;
}
#endregion
}
}

View File

@@ -0,0 +1,161 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TimetableDesigner.Core;
using TimetableDesigner.Services.TabNavigation;
using TimetableDesigner.Services;
using TimetableDesigner.ViewModels.Models;
using TimetableDesigner.Properties;
using TimetableDesigner.Customs;
using TimetableDesigner.Services.Project;
using System.Windows.Input;
using TimetableDesigner.Commands;
using System.Diagnostics;
using TimetableDesigner.Services.MessageBox;
namespace TimetableDesigner.ViewModels.Views
{
public class GroupEditViewModel : BaseViewViewModel
{
#region FIELDS
private IProjectService _projectService;
private IMessageBoxService _messageBoxService;
private GroupViewModel _group;
private string _newSubgroupName;
#endregion
#region PROPERTIES
public GroupViewModel Group
{
get => _group;
set
{
if (_group != value)
{
_group = value;
NotifyPropertyChanged(nameof(Group));
}
}
}
public string Name
{
get => _group.Name;
set
{
if (_group.Name != value)
{
_group.Name = value;
NotifyPropertyChanged(nameof(Name));
TabItem? tab = ServiceProvider.Instance.GetService<ITabNavigationService>().Tabs.Where(tab => tab.ViewModel == this).FirstOrDefault();
if (tab != null)
{
tab.Title = $"{Resources.Tabs_GroupEdit}: {_group.Name}";
}
}
}
}
public ObservableDictionary<SubgroupViewModel, bool> Subgroups => new ObservableDictionary<SubgroupViewModel, bool>(_projectService.ProjectViewModel.Subgroups.ToDictionary(sg => sg, Group.AssignedSubgroups.Contains));
public string NewSubgroupName
{
get => _newSubgroupName;
set
{
if (_newSubgroupName != value)
{
_newSubgroupName = value;
NotifyPropertyChanged(nameof(NewSubgroupName));
}
}
}
public ICommand AddSubgroupCommand { get; set; }
public ICommand EditSubgroupAssignmentCommand { get; set; }
public ICommand DeleteSubgroupCommand { get; set; }
#endregion
#region CONSTRUCTORS
public GroupEditViewModel() : this(new GroupViewModel(new Group()))
{ }
public GroupEditViewModel(GroupViewModel group)
{
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
_messageBoxService = ServiceProvider.Instance.GetService<IMessageBoxService>();
_group = group;
_newSubgroupName = string.Empty;
AddSubgroupCommand = new RelayCommand<object>(args => AddSubgroup());
EditSubgroupAssignmentCommand = new RelayCommand<SubgroupViewModel>(EditSubgroupAssignment);
DeleteSubgroupCommand = new RelayCommand<SubgroupViewModel>(DeleteSubgroup);
}
#endregion
#region PRIVATE METHODS
private void AddSubgroup()
{
Subgroup subgroup = new Subgroup()
{
Name = NewSubgroupName
};
SubgroupViewModel subgroupViewModel = new SubgroupViewModel(subgroup);
_projectService.ProjectViewModel.Subgroups.Add(subgroupViewModel);
Group.AddSubgroup(subgroupViewModel);
NotifyPropertyChanged(nameof(Subgroups));
NewSubgroupName = string.Empty;
}
private void EditSubgroupAssignment(SubgroupViewModel subgroup)
{
bool assigned = Subgroups[subgroup];
if (assigned)
{
Group.RemoveSubgroup(subgroup);
}
else
{
Group.AddSubgroup(subgroup);
}
NotifyPropertyChanged(nameof(Subgroups));
}
private void DeleteSubgroup(SubgroupViewModel subgroup)
{
MessageBoxQuestionResult result = _messageBoxService.ShowQuestion(Resources.GroupEdit_Message_SubgroupDelete, true);
if (result == MessageBoxQuestionResult.Yes)
{
foreach (GroupViewModel group in _projectService.ProjectViewModel.Groups)
{
group.RemoveSubgroup(subgroup);
}
_projectService.ProjectViewModel.Subgroups.Remove(subgroup);
NotifyPropertyChanged(nameof(Subgroups));
}
}
#endregion
}
}

View File

@@ -0,0 +1,271 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using TimetableDesigner.Commands;
using System.Windows.Navigation;
using TimetableDesigner.Core;
using System.Windows;
using TimetableDesigner.Properties;
using System.Reflection;
using TimetableDesigner.ViewModels.Models;
using System.Windows.Data;
using TimetableDesigner.Services.MessageBox;
using System.ComponentModel.Design;
using TimetableDesigner.Services;
using TimetableDesigner.Services.TabNavigation;
using TimetableDesigner.Services.Project;
using System.Drawing;
namespace TimetableDesigner.ViewModels.Views
{
class MainViewModel : BaseViewViewModel
{
#region FIELDS
private IMessageBoxService _messageBoxService;
private ITabNavigationService _tabNavigationService;
private IProjectService _projectService;
#endregion
#region PROPERTIES
// Observable services
public IProjectService ProjectService => _projectService;
public ITabNavigationService TabNavigationService => _tabNavigationService;
// Tabs
public ObservableCollection<TabItem> Tabs => _tabNavigationService.Tabs;
public TabItem SelectedTab => _tabNavigationService.SelectedTab;
// Commands
public ICommand NewProjectCommand { get; set; }
public ICommand OpenProjectCommand { get; set; }
public ICommand ProjectSettingsCommand { get; set; }
public ICommand NewClassroomCommand { get; set; }
public ICommand EditClassroomCommand { get; set; }
public ICommand RemoveClassroomCommand { get; set; }
public ICommand NewTeacherCommand { get; set; }
public ICommand EditTeacherCommand { get; set; }
public ICommand RemoveTeacherCommand { get; set; }
public ICommand NewGroupCommand { get; set; }
public ICommand EditGroupCommand { get; set; }
public ICommand RemoveGroupCommand { get; set; }
public ICommand RemoveSubgroupCommand { get; set; }
// Others
public string Version { get; set; }
#endregion
#region CONSTRUCTORS
public MainViewModel()
{
_messageBoxService = ServiceProvider.Instance.GetService<IMessageBoxService>();
_tabNavigationService = ServiceProvider.Instance.GetService<ITabNavigationService>();
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
NewProjectCommand = new RelayCommand<object>(param => NewProject());
OpenProjectCommand = new RelayCommand<object>(param => OpenProject());
ProjectSettingsCommand = new RelayCommand<object>(param => ProjectSettings());
NewClassroomCommand = new RelayCommand<object>(param => NewClassroom());
EditClassroomCommand = new RelayCommand<ClassroomViewModel>(EditClassroom);
RemoveClassroomCommand = new RelayCommand<ClassroomViewModel>(DeleteClassroom);
NewTeacherCommand = new RelayCommand<object>(param => NewTeacher());
EditTeacherCommand = new RelayCommand<TeacherViewModel>(EditTeacher);
RemoveTeacherCommand = new RelayCommand<TeacherViewModel>(DeleteTeacher);
NewGroupCommand = new RelayCommand<object>(param => NewGroup());
EditGroupCommand = new RelayCommand<GroupViewModel>(EditGroup);
RemoveGroupCommand = new RelayCommand<GroupViewModel>(DeleteGroup);
RemoveSubgroupCommand = new RelayCommand<SubgroupViewModel>(DeleteSubgroup);
Version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
TabItem welcomeTab = new TabItem()
{
Title = Resources.Tabs_Welcome,
ViewModel = new WelcomeViewModel()
};
_tabNavigationService.AddAndActivate(welcomeTab);
}
#endregion
#region PRIVATE METHODS
private void OpenProject()
{
}
private void NewProject()
{
if (ProjectService.ProjectViewModel is not null)
{
MessageBoxQuestionResult result = _messageBoxService.ShowQuestion(Resources.Main_Message_SaveCurrentProject);
switch (result)
{
case MessageBoxQuestionResult.Yes: break;
case MessageBoxQuestionResult.No: break;
default: return;
}
}
_tabNavigationService.CloseAll();
_projectService.New();
ProjectSettings();
}
private void ProjectSettings()
{
if (ProjectService.ProjectViewModel is not null)
{
TabItem projectSettingsTab = new TabItem()
{
Title = Resources.Tabs_ProjectSettings,
IsClosable = true,
ViewModel = new ProjectSettingsViewModel()
};
_tabNavigationService.AddAndActivate(projectSettingsTab);
}
}
private void NewClassroom()
{
if (ProjectService.ProjectViewModel is not null)
{
Classroom classroom = new Classroom()
{
Name = Resources.Global_DefaultClassroomName
};
ClassroomViewModel classroomVM = new ClassroomViewModel(classroom);
ProjectService.ProjectViewModel.Classrooms.Add(classroomVM);
EditClassroom(classroomVM);
}
}
private void EditClassroom(ClassroomViewModel classroomViewModel)
{
if (ProjectService.ProjectViewModel is not null)
{
TabItem classroomEditTab = new TabItem()
{
Title = $"{Resources.Tabs_ClassroomEdit}: {classroomViewModel.Name}",
IsClosable = true,
ViewModel = new ClassroomEditViewModel(classroomViewModel)
};
_tabNavigationService.AddAndActivate(classroomEditTab);
}
}
private void DeleteClassroom(ClassroomViewModel classroomViewModel)
{
if (ProjectService.ProjectViewModel is not null)
{
ProjectService.ProjectViewModel.Classrooms.Remove(classroomViewModel);
}
}
private void NewTeacher()
{
if (ProjectService.ProjectViewModel is not null)
{
Teacher teacher = new Teacher()
{
Name = Resources.Global_DefaultTeacherName
};
TeacherViewModel teacherVM = new TeacherViewModel(teacher);
ProjectService.ProjectViewModel.Teachers.Add(teacherVM);
EditTeacher(teacherVM);
}
}
private void EditTeacher(TeacherViewModel teacherViewModel)
{
if (ProjectService.ProjectViewModel is not null)
{
TabItem teacherEditTab = new TabItem()
{
Title = $"{Resources.Tabs_TeacherEdit}: {teacherViewModel.Name}",
IsClosable = true,
ViewModel = new TeacherEditViewModel(teacherViewModel)
};
_tabNavigationService.AddAndActivate(teacherEditTab);
}
}
private void DeleteTeacher(TeacherViewModel teacherViewModel)
{
if (ProjectService.ProjectViewModel is not null)
{
ProjectService.ProjectViewModel.Teachers.Remove(teacherViewModel);
}
}
private void NewGroup()
{
if (ProjectService.ProjectViewModel is not null)
{
Group group = new Group()
{
Name = Resources.Global_DefaultGroupName
};
GroupViewModel groupVM = new GroupViewModel(group);
ProjectService.ProjectViewModel.Groups.Add(groupVM);
EditGroup(groupVM);
}
}
private void EditGroup(GroupViewModel groupViewModel)
{
if (ProjectService.ProjectViewModel is not null)
{
TabItem groupEditTab = new TabItem()
{
Title = $"{Resources.Tabs_GroupEdit}: {groupViewModel.Name}",
IsClosable = true,
ViewModel = new GroupEditViewModel(groupViewModel)
};
_tabNavigationService.AddAndActivate(groupEditTab);
}
}
private void DeleteGroup(GroupViewModel groupViewModel)
{
if (ProjectService.ProjectViewModel is not null)
{
ProjectService.ProjectViewModel.Groups.Remove(groupViewModel);
}
}
private void DeleteSubgroup(SubgroupViewModel subgroupViewModel)
{
if (ProjectService.ProjectViewModel is not null)
{
MessageBoxQuestionResult result = _messageBoxService.ShowQuestion(Resources.Main_Treeview_Subgroups_Message_Remove, true);
if (result == MessageBoxQuestionResult.Yes)
{
foreach (GroupViewModel group in ProjectService.ProjectViewModel.Groups)
{
group.RemoveSubgroup(subgroupViewModel);
}
_projectService.ProjectViewModel.Subgroups.Remove(subgroupViewModel);
}
}
}
#endregion
}
}

View File

@@ -10,17 +10,22 @@ using System.Windows;
using System.Windows.Input;
using TimetableDesigner.Commands;
using TimetableDesigner.Core;
using TimetableDesigner.MessageBox;
using TimetableDesigner.Customs;
using TimetableDesigner.Properties;
using TimetableDesigner.ViewModels.Base;
using TimetableDesigner.Services;
using TimetableDesigner.Services.MessageBox;
using TimetableDesigner.Services.Project;
using TimetableDesigner.ViewModels.Models;
namespace TimetableDesigner.ViewModels
namespace TimetableDesigner.ViewModels.Views
{
public class ProjectSettingsTabViewModel : BaseTabViewModel
public class ProjectSettingsViewModel : BaseViewViewModel
{
#region FIELDS
private IMessageBoxService _messageBoxService;
private IProjectService _projectService;
private string _newDayName;
private DateTime? _newSlotFrom;
private DateTime? _newSlotTo;
@@ -31,13 +36,10 @@ namespace TimetableDesigner.ViewModels
#region PROPERTIES
public ICommand AddDayCommand { get; set; }
public ICommand AddSlotCommand { get; set; }
public ICommand RemoveDayCommand { get; set; }
public ICommand RemoveSlotCommand { get; set; }
public ProjectViewModel? Project { get; set; }
// Project
public ProjectViewModel? Project => _projectService.ProjectViewModel;
// Fields
public string NewDayName
{
get => _newDayName;
@@ -67,15 +69,22 @@ namespace TimetableDesigner.ViewModels
}
}
// Commands
public ICommand AddDayCommand { get; set; }
public ICommand AddSlotCommand { get; set; }
public ICommand RemoveDayCommand { get; set; }
public ICommand RemoveSlotCommand { get; set; }
#endregion
#region CONSTRUCTORS
public ProjectSettingsTabViewModel() : base()
public ProjectSettingsViewModel()
{
Project = new ProjectViewModel(new Project());
_messageBoxService = ServiceProvider.Instance.GetService<IMessageBoxService>();
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
AddDayCommand = new RelayCommand<object>(param => AddDay());
AddSlotCommand = new RelayCommand<object>(param => AddSlot());
@@ -95,24 +104,34 @@ namespace TimetableDesigner.ViewModels
private void AddDay()
{
if (!string.IsNullOrWhiteSpace(NewDayName))
if (Project is not null && !string.IsNullOrWhiteSpace(NewDayName))
{
Project.TimetableTemplate.AddDay(new TimetableDay(NewDayName));
NewDayName = string.Empty;
}
}
private void RemoveDay(TimetableDay day) => Project.TimetableTemplate.RemoveDay(day);
private void RemoveDay(TimetableDay day)
{
if (Project is not null)
{
foreach (TeacherViewModel teacher in Project.Teachers)
{
teacher.RemoveDay(day);
}
Project.TimetableTemplate.RemoveDay(day);
}
}
private void AddSlot()
{
if (NewSlotFrom.HasValue && NewSlotTo.HasValue)
if (Project is not null && NewSlotFrom.HasValue && NewSlotTo.HasValue)
{
TimeOnly from = new TimeOnly(NewSlotFrom.Value.Hour, NewSlotFrom.Value.Minute);
TimeOnly to = new TimeOnly(NewSlotTo.Value.Hour, NewSlotTo.Value.Minute);
if (from >= to)
{
MessageBoxService.ShowError(Resources.ProjectSettings_Message_FromHigherThanTo);
_messageBoxService.ShowError(Resources.ProjectSettings_Message_FromHigherThanTo);
return;
}
@@ -128,7 +147,7 @@ namespace TimetableDesigner.ViewModels
}
catch (ArgumentException)
{
MessageBoxService.ShowError(Resources.ProjectSettings_Message_SlotCollision);
_messageBoxService.ShowError(Resources.ProjectSettings_Message_SlotCollision);
}
}
}

View File

@@ -7,19 +7,24 @@ using System.Threading.Tasks;
using System.Windows.Input;
using TimetableDesigner.Commands;
using TimetableDesigner.Core;
using TimetableDesigner.MessageBox;
using TimetableDesigner.Customs;
using TimetableDesigner.Properties;
using TimetableDesigner.ViewModels.Base;
using TimetableDesigner.Services;
using TimetableDesigner.Services.MessageBox;
using TimetableDesigner.Services.Project;
using TimetableDesigner.Services.TabNavigation;
using TimetableDesigner.ViewModels.Models;
namespace TimetableDesigner.ViewModels
namespace TimetableDesigner.ViewModels.Views
{
public class TeacherEditTabViewModel : BaseTabViewModel
public class TeacherEditViewModel : BaseViewViewModel
{
#region FIELDS
private IMessageBoxService _messageBoxService;
private IProjectService _projectService;
private TeacherViewModel _teacher;
private TimetableTemplateViewModel _timetableTemplate;
private TimetableDay _selectedDay;
@@ -45,15 +50,23 @@ namespace TimetableDesigner.ViewModels
}
}
}
public TimetableTemplateViewModel TimetableTemplate
public TimetableTemplateViewModel? TimetableTemplate => _projectService.ProjectViewModel?.TimetableTemplate;
public string Name
{
get => _timetableTemplate;
get => _teacher.Name;
set
{
if (value != _timetableTemplate)
if (_teacher.Name != value)
{
_timetableTemplate = value;
NotifyPropertyChanged(nameof(TimetableTemplate));
_teacher.Name = value;
NotifyPropertyChanged(nameof(Teacher));
TabItem? tab = ServiceProvider.Instance.GetService<ITabNavigationService>().Tabs.Where(tab => tab.ViewModel == this).FirstOrDefault();
if (tab != null)
{
tab.Title = $"{Resources.Tabs_ClassroomEdit}: {_teacher.Name}";
}
}
}
}
@@ -117,13 +130,15 @@ namespace TimetableDesigner.ViewModels
#region CONSTRUCTORS
public TeacherEditTabViewModel() : this(new TeacherViewModel(new Core.Teacher()), new TimetableTemplateViewModel(new Core.TimetableTemplate()))
public TeacherEditViewModel() : this(new TeacherViewModel(new Teacher()))
{ }
public TeacherEditTabViewModel(TeacherViewModel teacher, TimetableTemplateViewModel timetableTemplate) : base()
public TeacherEditViewModel(TeacherViewModel teacher)
{
_messageBoxService = ServiceProvider.Instance.GetService<IMessageBoxService>();
_projectService = ServiceProvider.Instance.GetService<IProjectService>();
_teacher = teacher;
_timetableTemplate = timetableTemplate;
AddDayCommand = new RelayCommand<object>(param => AddDay());
RemoveDayCommand = new RelayCommand<TimetableDay>(RemoveDay);
@@ -161,7 +176,7 @@ namespace TimetableDesigner.ViewModels
TimeOnly to = new TimeOnly(NewHourTo.Value.Hour, NewHourTo.Value.Minute);
if (from >= to)
{
MessageBoxService.ShowError(Resources.TeacherEdit_Message_FromHigherThanTo);
_messageBoxService.ShowError(Resources.TeacherEdit_Message_FromHigherThanTo);
return;
}
@@ -171,7 +186,7 @@ namespace TimetableDesigner.ViewModels
}
catch (ArgumentException)
{
MessageBoxService.ShowError(Resources.TeacherEdit_Message_HourCollision);
_messageBoxService.ShowError(Resources.TeacherEdit_Message_HourCollision);
}
}
NotifyPropertyChanged(nameof(SelectedDayHours));

View File

@@ -3,15 +3,15 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TimetableDesigner.ViewModels.Base;
using TimetableDesigner.Customs;
namespace TimetableDesigner.ViewModels
namespace TimetableDesigner.ViewModels.Views
{
public class WelcomeTabViewModel : BaseTabViewModel
public class WelcomeViewModel : BaseViewViewModel
{
#region CONSTRUCTORS
public WelcomeTabViewModel()
public WelcomeViewModel()
{ }
#endregion

View File

@@ -1,35 +0,0 @@
<UserControl x:Class="TimetableDesigner.Views.ClassroomEditTabView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:p = "clr-namespace:TimetableDesigner.Properties"
xmlns:vm="clr-namespace:TimetableDesigner.ViewModels"
xmlns:local="clr-namespace:TimetableDesigner.Views"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.DataContext>
<vm:ClassroomEditTabViewModel/>
</UserControl.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Grid.Column="0" Grid.Row="0" Content="{x:Static p:Resources.ClassroomEdit_Name}"/>
<TextBox Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="0" Margin="5" Text="{Binding Classroom.Name}" MaxLines="1"/>
<Label Grid.Column="0" Grid.Row="1" Content="{x:Static p:Resources.ClassroomEdit_Description}"/>
<TextBox Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="1" Margin="5" MinLines="3" Text="{Binding Classroom.Description}"/>
<Label Grid.Column="0" Grid.Row="2" Content="{x:Static p:Resources.ClassroomEdit_Capacity}"/>
<xctk:IntegerUpDown Grid.Column="1" Grid.Row="2" Margin="5" Minimum="1" IsEnabled="{Binding Classroom.IsCapacityLimited}" Value="{Binding Classroom.Capacity}"/>
<CheckBox Grid.Column="2" Grid.Row="2" Margin="5" Content="{x:Static p:Resources.ClassroomEdit_CapacityIsLimited}" IsChecked="{Binding Classroom.IsCapacityLimited}" VerticalAlignment="Center"/>
</Grid>
</UserControl>

View File

@@ -0,0 +1,51 @@
<UserControl x:Class="TimetableDesigner.Views.ClassroomEditView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:p = "clr-namespace:TimetableDesigner.Properties"
xmlns:vm="clr-namespace:TimetableDesigner.ViewModels.Views"
xmlns:local="clr-namespace:TimetableDesigner.Views"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.DataContext>
<vm:ClassroomEditViewModel/>
</UserControl.DataContext>
<ScrollViewer>
<StackPanel>
<GroupBox VerticalAlignment="Top" Header="{x:Static p:Resources.ClassroomEdit_Groups_Basics}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Grid.Column="0" Grid.Row="0" Content="{x:Static p:Resources.ClassroomEdit_Name}"/>
<TextBox Grid.Column="1" Grid.Row="0" Margin="5" Text="{Binding Name}" MaxLines="1"/>
<Label Grid.Column="0" Grid.Row="1" Content="{x:Static p:Resources.ClassroomEdit_Description}"/>
<TextBox Grid.Column="1" Grid.Row="1" Margin="5" MinLines="3" Text="{Binding Classroom.Description}" AcceptsReturn="True"/>
</Grid>
</GroupBox>
<GroupBox VerticalAlignment="Top" Header="{x:Static p:Resources.ClassroomEdit_Groups_Capacity}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Grid.Column="0" Grid.Row="2" Content="{x:Static p:Resources.ClassroomEdit_Capacity}"/>
<xctk:IntegerUpDown Grid.Column="1" Grid.Row="2" Margin="5" Minimum="1" IsEnabled="{Binding Classroom.IsCapacityLimited}" Value="{Binding Classroom.Capacity}"/>
<CheckBox Grid.Column="2" Grid.Row="2" Margin="5" Content="{x:Static p:Resources.ClassroomEdit_CapacityIsLimited}" IsChecked="{Binding Classroom.IsCapacityLimited}" VerticalAlignment="Center"/>
</Grid>
</GroupBox>
</StackPanel>
</ScrollViewer>
</UserControl>

View File

@@ -15,9 +15,9 @@ using System.Windows.Shapes;
namespace TimetableDesigner.Views
{
public partial class ProjectSettingsTabView : UserControl
public partial class ClassroomEditView : UserControl
{
public ProjectSettingsTabView()
public ClassroomEditView()
{
InitializeComponent();
}

View File

@@ -0,0 +1,72 @@
<UserControl x:Class="TimetableDesigner.Views.GroupEditView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:p = "clr-namespace:TimetableDesigner.Properties"
xmlns:vm="clr-namespace:TimetableDesigner.ViewModels.Views"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:TimetableDesigner.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.DataContext>
<vm:GroupEditViewModel/>
</UserControl.DataContext>
<ScrollViewer>
<StackPanel>
<GroupBox Header="{x:Static p:Resources.GroupEdit_Groups_Basics}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Grid.Column="0" Grid.Row="0" Content="{x:Static p:Resources.GroupEdit_Name}"/>
<TextBox Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="0" Margin="5" Text="{Binding Name}" MaxLines="1"/>
<Label Grid.Column="0" Grid.Row="1" Content="{x:Static p:Resources.GroupEdit_Description}"/>
<TextBox Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="1" Margin="5" MinLines="3" Text="{Binding Group.Description}"/>
</Grid>
</GroupBox>
<GroupBox Header="{x:Static p:Resources.GroupEdit_Groups_Subgroups}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListBox Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Margin="5" MinHeight="100" HorizontalContentAlignment="Stretch" ItemsSource="{Binding Subgroups}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Key.Name}"
IsChecked="{Binding Value}"
Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}, Path=DataContext}"
Command="{Binding DataContext.EditSubgroupAssignmentCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
CommandParameter="{Binding Key}">
<CheckBox.ContextMenu>
<ContextMenu>
<MenuItem Header="{x:Static p:Resources.GroupEdit_DeleteSubgroup}"
Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}, Path=PlacementTarget.Tag.DeleteSubgroupCommand}"
CommandParameter="{Binding Key}"/>
</ContextMenu>
</CheckBox.ContextMenu>
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Label Grid.Row="2" Grid.Column="0" Margin="5" Content="{x:Static p:Resources.GroupEdit_NewSubgroupLabel}"/>
<TextBox Grid.Row="2" Grid.Column="1" MaxLines="1" Margin="5" Text="{Binding NewSubgroupName}"/>
<Button Grid.Row="2" Grid.Column="2" Margin="5" Command="{Binding AddSubgroupCommand}">
<Image Source="{StaticResource AddImage}" Width="20" Height="20"/>
</Button>
</Grid>
</GroupBox>
</StackPanel>
</ScrollViewer>
</UserControl>

View File

@@ -15,12 +15,9 @@ using System.Windows.Shapes;
namespace TimetableDesigner.Views
{
/// <summary>
/// Interaction logic for WelcomeTabView.xaml
/// </summary>
public partial class WelcomeTabView : UserControl
public partial class GroupEditView : UserControl
{
public WelcomeTabView()
public GroupEditView()
{
InitializeComponent();
}

View File

@@ -1,8 +1,7 @@
<rib:RibbonWindow x:Class="TimetableDesigner.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:TimetableDesigner.ViewModels"
xmlns:vmm="clr-namespace:TimetableDesigner.ViewModels.Models"
xmlns:vm="clr-namespace:TimetableDesigner.ViewModels.Views"
xmlns:p = "clr-namespace:TimetableDesigner.Properties"
xmlns:rib="urn:fluent-ribbon"
Height="450"
@@ -10,7 +9,7 @@
<rib:RibbonWindow.Title>
<MultiBinding StringFormat="Timetable Designer {0} ({1})">
<Binding Path="Version"/>
<Binding Path="Project.Name" FallbackValue="{x:Static p:Resources.Global_NoProjectLoadedTitle}"/>
<Binding Path="ProjectService.Project.Name" FallbackValue="{x:Static p:Resources.Global_NoProjectLoadedTitle}"/>
</MultiBinding>
</rib:RibbonWindow.Title>
<rib:RibbonWindow.DataContext>
@@ -33,12 +32,12 @@
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_File_NewOpen_Open}" Icon="{StaticResource OpenImage}" Command="{Binding OpenProjectCommand}"/>
<rib:DropDownButton Header="{x:Static p:Resources.Main_Ribbon_File_NewOpen_OpenRecent}" Icon="{StaticResource OpenRecentImage}"/>
</rib:RibbonGroupBox>
<rib:RibbonGroupBox Header="{x:Static p:Resources.Main_Ribbon_File_Save}" IsEnabled="{Binding Project, Converter={StaticResource IsNotNullToBooleanConverter}}">
<rib:RibbonGroupBox Header="{x:Static p:Resources.Main_Ribbon_File_Save}" IsEnabled="{Binding ProjectService.ProjectViewModel, Converter={StaticResource IsNotNullToBooleanConverter}}">
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_File_Save_Save}" Icon="{StaticResource SaveImage}"/>
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_File_Save_SaveAs}" Icon="{StaticResource SaveAsImage}"/>
</rib:RibbonGroupBox>
</rib:RibbonTabItem>
<rib:RibbonTabItem Header="{x:Static p:Resources.Main_Ribbon_Project}" IsEnabled="{Binding Project, Converter={StaticResource IsNotNullToBooleanConverter}}">
<rib:RibbonTabItem Header="{x:Static p:Resources.Main_Ribbon_Project}" IsEnabled="{Binding ProjectService.ProjectViewModel, Converter={StaticResource IsNotNullToBooleanConverter}}">
<rib:RibbonGroupBox Header="{x:Static p:Resources.Main_Ribbon_Project_Settings}">
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_Project_Settings_ProjectSettings}"
Command="{Binding ProjectSettingsCommand}"
@@ -47,13 +46,22 @@
<rib:RibbonGroupBox Header="{x:Static p:Resources.Main_Ribbon_Project_New}">
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_Project_New_NewClassroom}" Icon="{StaticResource ClassroomAddImage}" Command="{Binding NewClassroomCommand}"/>
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_Project_New_NewTeacher}" Icon="{StaticResource TeacherAddImage}" Command="{Binding NewTeacherCommand}"/>
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_Project_New_NewGroup}"/>
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_Project_New_NewSubgroup}"/>
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_Project_New_NewClass}"/>
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_Project_New_NewGroup}" Icon="{StaticResource GroupAddImage}" Command="{Binding NewGroupCommand}"/>
</rib:RibbonGroupBox>
<rib:RibbonGroupBox Header="{x:Static p:Resources.Main_Ribbon_Project_Import}">
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_Project_Import_ImportClassrooms}"/>
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_Project_Import_ImportTeachers}"/>
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_Project_Import_ImportGroups}"/>
</rib:RibbonGroupBox>
</rib:RibbonTabItem>
<rib:RibbonTabItem Header="{x:Static p:Resources.Main_Ribbon_Export}" IsEnabled="{Binding ProjectService.ProjectViewModel, Converter={StaticResource IsNotNullToBooleanConverter}}">
<rib:RibbonGroupBox Header="{x:Static p:Resources.Main_Ribbon_Export_Timetable}">
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_Export_Timetable_PDF}"/>
<rib:Button Header="{x:Static p:Resources.Main_Ribbon_Export_Timetable_XLS}"/>
</rib:RibbonGroupBox>
</rib:RibbonTabItem>
</rib:Ribbon>
<TreeView Grid.Row="1" Grid.Column="0" DataContext="{Binding Project}" Visibility="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=rib:RibbonWindow}, Path=DataContext.Project, Converter={StaticResource IsNullToVisibilityConverter}}">
<TreeView Grid.Row="1" Grid.Column="0" DataContext="{Binding ProjectService.ProjectViewModel}" Visibility="{Binding RelativeSource={RelativeSource Mode=Self}, Path=DataContext, Converter={StaticResource IsNullToVisibilityConverter}}">
<TreeViewItem>
<TreeViewItem.Header>
<StackPanel Orientation="Horizontal">
@@ -123,24 +131,70 @@
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
<TreeViewItem ItemsSource="{Binding Groups}">
<TreeViewItem.Header>
<StackPanel Orientation="Horizontal">
<Image Source="{StaticResource GroupImage}" Width="18" Height="18"/>
<Label Content="{x:Static p:Resources.Main_Treeview_Groups}"/>
</StackPanel>
</TreeViewItem.Header>
<TreeViewItem.ItemTemplate>
<DataTemplate>
<TreeViewItem Header="{Binding Name}" ItemsSource="{Binding AssignedSubgroups}" Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=rib:RibbonWindow}, Path=DataContext}">
<TreeViewItem.InputBindings>
<MouseBinding Gesture="LeftDoubleClick"/>
</TreeViewItem.InputBindings>
<TreeViewItem.ContextMenu>
<ContextMenu>
<MenuItem Header="{x:Static p:Resources.Main_Treeview_ContextMenu_EditTimetable}"/>
<MenuItem Header="{x:Static p:Resources.Main_Treeview_Groups_ContextMenu_Edit}"
Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}, Path=PlacementTarget.Tag.EditGroupCommand}"
CommandParameter="{Binding}"/>
<Separator/>
<MenuItem Header="{x:Static p:Resources.Main_Treeview_ContextMenu_Remove}"
Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}, Path=PlacementTarget.Tag.RemoveGroupCommand}"
CommandParameter="{Binding}"/>
</ContextMenu>
</TreeViewItem.ContextMenu>
<TreeViewItem.ItemTemplate>
<DataTemplate>
<TreeViewItem Header="{Binding Name}" Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=rib:RibbonWindow}, Path=DataContext}">
<TreeViewItem.InputBindings>
<MouseBinding Gesture="LeftDoubleClick"/>
</TreeViewItem.InputBindings>
<TreeViewItem.ContextMenu>
<ContextMenu>
<MenuItem Header="{x:Static p:Resources.Main_Treeview_ContextMenu_EditTimetable}"/>
<Separator/>
<MenuItem Header="{x:Static p:Resources.Main_Treeview_ContextMenu_Remove}"
Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}, Path=PlacementTarget.Tag.RemoveSubgroupCommand}"
CommandParameter="{Binding}"/>
</ContextMenu>
</TreeViewItem.ContextMenu>
</TreeViewItem>
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
</TreeViewItem>
</TreeView>
<GridSplitter Grid.Row="1" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Stretch" ShowsPreview="True" Width="2"/>
<TabControl Grid.Row="1" Grid.Column="2" ItemsSource="{Binding Tabs}" SelectedItem="{Binding SelectedTab}">
<TabControl Grid.Row="1" Grid.Column="2" DataContext="{Binding TabNavigationService}" ItemsSource="{Binding Tabs}" SelectedItem="{Binding SelectedTab, Mode=OneWay}">
<TabControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding TabImage}"
Visibility="{Binding TabImage, Converter={StaticResource IsNullToVisibilityConverter}}"
<Image Source="{Binding Image}"
Visibility="{Binding Image, Converter={StaticResource IsNullToVisibilityConverter}}"
Width="15"
Height="15"/>
<TextBlock Text="{Binding TabTitle}"/>
<TextBlock Text="{Binding Title}"/>
<Button BorderThickness="0"
Background="Transparent"
Margin="5,0,0,0"
Visibility="{Binding IsTabClosable, Converter={StaticResource boolToVisibilityConverter}}"
Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}, Path=DataContext.CloseTabCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}, Path=DataContext}">
Visibility="{Binding IsClosable, Converter={StaticResource boolToVisibilityConverter}}"
Command="{Binding CloseCommand}">
<Image Source="{StaticResource CloseImage}"
Width="15"
Height="15"/>
@@ -150,7 +204,7 @@
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<ContentControl Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}, Path=DataContext.SelectedTab, UpdateSourceTrigger = PropertyChanged, Converter={StaticResource ViewModelToViewConverter}}"/>
<ContentControl Content="{Binding ViewModel, Converter={StaticResource ViewModelToViewConverter}}"/>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>

View File

@@ -1,15 +1,15 @@
<UserControl x:Class="TimetableDesigner.Views.ProjectSettingsTabView"
<UserControl x:Class="TimetableDesigner.Views.ProjectSettingsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vm="clr-namespace:TimetableDesigner.ViewModels"
xmlns:vm="clr-namespace:TimetableDesigner.ViewModels.Views"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:p = "clr-namespace:TimetableDesigner.Properties"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.DataContext>
<vm:ProjectSettingsTabViewModel/>
<vm:ProjectSettingsViewModel/>
</UserControl.DataContext>
<ScrollViewer>
<StackPanel>
@@ -44,7 +44,7 @@
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Content="{x:Static p:Resources.ProjectSettings_Days}"/>
<Border Grid.Row="1" Grid.Column="0" Margin="5" BorderThickness="1" BorderBrush="DarkGray">
<Border Grid.Row="1" Grid.Column="0" Margin="5" BorderThickness="0.3" BorderBrush="Black">
<ItemsControl ItemsSource="{Binding Project.TimetableTemplate.Days}" HorizontalContentAlignment="Stretch" MinHeight="100">
<ItemsControl.ItemTemplate>
<DataTemplate>
@@ -77,7 +77,7 @@
</Button>
</Grid>
<Label Grid.Row="0" Grid.Column="1" Content="{x:Static p:Resources.ProjectSettings_Hours}"/>
<Border Grid.Row="1" Grid.Column="1" Margin="5" BorderThickness="1" BorderBrush="DarkGray">
<Border Grid.Row="1" Grid.Column="1" Margin="5" BorderThickness="0.3" BorderBrush="Black">
<ItemsControl ItemsSource="{Binding Project.TimetableTemplate.Slots}" HorizontalContentAlignment="Stretch" MinHeight="100">
<ItemsControl.ItemTemplate>
<DataTemplate>

View File

@@ -15,12 +15,9 @@ using System.Windows.Shapes;
namespace TimetableDesigner.Views
{
/// <summary>
/// Interaction logic for TeacherEditTabView.xaml
/// </summary>
public partial class TeacherEditTabView : UserControl
public partial class ProjectSettingsView : UserControl
{
public TeacherEditTabView()
public ProjectSettingsView()
{
InitializeComponent();
}

View File

@@ -1,37 +1,21 @@
<UserControl x:Class="TimetableDesigner.Views.TeacherEditTabView"
<UserControl x:Class="TimetableDesigner.Views.TeacherEditView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:p = "clr-namespace:TimetableDesigner.Properties"
xmlns:vm="clr-namespace:TimetableDesigner.ViewModels"
xmlns:vm="clr-namespace:TimetableDesigner.ViewModels.Views"
xmlns:local="clr-namespace:TimetableDesigner.Views" xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.DataContext>
<vm:TeacherEditTabViewModel/>
<vm:TeacherEditViewModel/>
</UserControl.DataContext>
<ScrollViewer>
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Grid.Column="0" Grid.Row="0" Content="{x:Static p:Resources.TeacherEdit_Name}"/>
<TextBox Grid.Column="1" Grid.Row="0" Margin="5" Text="{Binding Teacher.Name}" MaxLines="1"/>
<Label Grid.Column="0" Grid.Row="1" Content="{x:Static p:Resources.TeacherEdit_Description}"/>
<TextBox Grid.Column="1" Grid.Row="1" Margin="5" MinLines="3" Text="{Binding Teacher.Description}"/>
</Grid>
<StackPanel>
<Label Content="{x:Static p:Resources.TeacherEdit_AvailabilityHours}"/>
<GroupBox Header="{x:Static p:Resources.TeacherEdit_Groups_Basics}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
@@ -39,8 +23,28 @@
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border Grid.Column="0" Grid.Row="0" Margin="5" BorderThickness="1" BorderBrush="DarkGray">
<ListBox MinHeight="100" ItemsSource="{Binding Teacher.AvailabilityHours.Keys}" SelectedItem="{Binding SelectedDay}" HorizontalContentAlignment="Stretch">
<Label Grid.Column="0" Grid.Row="0" Content="{x:Static p:Resources.TeacherEdit_Name}"/>
<TextBox Grid.Column="1" Grid.Row="0" Margin="5" Text="{Binding Name}" MaxLines="1"/>
<Label Grid.Column="0" Grid.Row="1" Content="{x:Static p:Resources.TeacherEdit_Description}"/>
<TextBox Grid.Column="1" Grid.Row="1" Margin="5" MinLines="3" Text="{Binding Teacher.Description}" AcceptsReturn="True"/>
</Grid>
</GroupBox>
<GroupBox Header="{x:Static p:Resources.TeacherEdit_Groups_AvailabilityHours}">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Grid.Column="0" Grid.Row="0" Content="{x:Static p:Resources.TeacherEdit_Days}"/>
<Label Grid.Column="2" Grid.Row="0" Content="{x:Static p:Resources.TeacherEdit_Hours}"/>
<ListBox Grid.Column="0" Grid.Row="1" Margin="5" MinHeight="100" ItemsSource="{Binding Teacher.AvailabilityHours.Keys}" SelectedItem="{Binding SelectedDay}" HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch" Margin="5">
@@ -60,10 +64,8 @@
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Border>
<Image Grid.Column="1" Grid.Row="0" VerticalAlignment="Center" Source="{StaticResource RightArrowImage}" Width="20" Height="20"/>
<Border Grid.Column="2" Grid.Row="0" Margin="5" BorderThickness="1" BorderBrush="DarkGray">
<ListBox ItemsSource="{Binding SelectedDayHours}" HorizontalContentAlignment="Stretch">
<Image Grid.Column="1" Grid.Row="1" VerticalAlignment="Center" Source="{StaticResource RightArrowImage}" Width="20" Height="20"/>
<ListBox Grid.Column="2" Grid.Row="1" Margin="5" ItemsSource="{Binding SelectedDayHours}" HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch" Margin="5">
@@ -87,33 +89,33 @@
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Border>
<Grid Grid.Column="0" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ComboBox Grid.Column="0" Margin="5" ItemsSource="{Binding TimetableTemplate.Days}" SelectedItem="{Binding SelectedNewDay}" DisplayMemberPath="Name"/>
<Button Grid.Column="1" Margin="5" Width="26" Height="26" Command="{Binding AddDayCommand}">
<Image Source="{StaticResource AddImage}" Width="20" Height="20"/>
</Button>
<Grid Grid.Column="0" Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ComboBox Grid.Column="0" Margin="5" ItemsSource="{Binding TimetableTemplate.Days}" SelectedItem="{Binding SelectedNewDay}" DisplayMemberPath="Name" VerticalContentAlignment="Center"/>
<Button Grid.Column="1" Margin="5" Width="26" Height="26" Command="{Binding AddDayCommand}">
<Image Source="{StaticResource AddImage}" Width="20" Height="20"/>
</Button>
</Grid>
<Grid Grid.Column="2" Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<xctk:DateTimeUpDown Grid.Column="0" Margin="5" Format="ShortTime" Value="{Binding NewHourFrom}"/>
<Label Grid.Column="1" Margin="5" Content="-"/>
<xctk:DateTimeUpDown Grid.Column="2" Margin="5" Format="ShortTime" Value="{Binding NewHourTo}"/>
<Button Grid.Column="3" Margin="5" Command="{Binding AddHourCommand}" Width="26" Height="26">
<Image Source="{StaticResource AddImage}" Width="20" Height="20"/>
</Button>
</Grid>
</Grid>
<Grid Grid.Column="2" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<xctk:DateTimeUpDown Grid.Column="0" Margin="5" Format="ShortTime" Value="{Binding NewHourFrom}"/>
<Label Grid.Column="1" Margin="5" Content="-"/>
<xctk:DateTimeUpDown Grid.Column="2" Margin="5" Format="ShortTime" Value="{Binding NewHourTo}"/>
<Button Grid.Column="3" Margin="5" Command="{Binding AddHourCommand}" Width="26" Height="26">
<Image Source="{StaticResource AddImage}" Width="20" Height="20"/>
</Button>
</Grid>
</Grid>
</StackPanel>
</StackPanel>
</GroupBox>
</StackPanel>
</ScrollViewer>
</UserControl>

View File

@@ -15,12 +15,9 @@ using System.Windows.Shapes;
namespace TimetableDesigner.Views
{
/// <summary>
/// Interaction logic for ClassroomEditTabView.xaml
/// </summary>
public partial class ClassroomEditTabView : UserControl
public partial class TeacherEditView : UserControl
{
public ClassroomEditTabView()
public TeacherEditView()
{
InitializeComponent();
}

View File

@@ -1,14 +1,16 @@
<UserControl x:Class="TimetableDesigner.Views.WelcomeTabView"
<UserControl x:Class="TimetableDesigner.Views.WelcomeView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vm="clr-namespace:TimetableDesigner.ViewModels"
xmlns:vm="clr-namespace:TimetableDesigner.ViewModels.Views"
xmlns:c="clr-namespace:TimetableDesigner.Controls"
mc:Ignorable="d">
<UserControl.DataContext>
<vm:WelcomeTabViewModel/>
<vm:WelcomeViewModel/>
</UserControl.DataContext>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<Label Content="Open or create new project to begin"/>
<c:TimetableEditorControl/>
</StackPanel>
</UserControl>

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace TimetableDesigner.Views
{
public partial class WelcomeView : UserControl
{
public WelcomeView()
{
InitializeComponent();
}
}
}