Aufgeräumt und mit Kommentaren versehen (KeyedCollection dabei eingebaut)

This commit is contained in:
mdn 2015-12-05 23:39:07 +01:00
parent 2b2f31371a
commit e272f62629
14 changed files with 242 additions and 305 deletions

View file

@ -7,7 +7,7 @@ namespace TimeScheduler.Common
/// Vorbereitung: /// Vorbereitung:
/// <code language="xaml"> /// <code language="xaml">
/// &lt;FrameworkElement.Resources&gt; /// &lt;FrameworkElement.Resources&gt;
/// &tl;c:BindingProxy x:Key="proxy" Data="{Binding}"&gt; /// &lt;c:BindingProxy x:Key="proxy" Data="{Binding}"&gt;
/// &lt;/FrameworkElement.Resources&gt; /// &lt;/FrameworkElement.Resources&gt;
/// </code> /// </code>
/// Verwendung an einer anderen Stelle: /// Verwendung an einer anderen Stelle:

View file

@ -1,32 +1,45 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TimeScheduler.Common namespace TimeScheduler.Common
{ {
/// <summary>Mathematische Funktionen</summary>
public static class MathUtil public static class MathUtil
{ {
public static int IncrementDecrementNumber(string num, int minValue, int maxVal, bool increment) /// <summary>Verringert/Erhöht die Zahl</summary>
/// <param name="num">Nummer die verändert werden soll</param>
/// <param name="minValue">Minmal erlaubter Wert</param>
/// <param name="maxValue">Maximal erlaubter Wert</param>
/// <param name="increment">Veränderungsrichtung</param>
/// <returns>Der veränderte Wert</returns>
public static int IncrementDecrementNumber(string num, int minValue, int maxValue, bool increment)
{ {
int newNum = ValidateNumber(num, minValue, maxVal); int newNum = ValidateNumber(num, minValue, maxValue);
if (increment) if (increment)
newNum = Math.Min(newNum + 1, maxVal); newNum = Math.Min(newNum + 1, maxValue);
else else
newNum = Math.Max(newNum - 1, 0); newNum = Math.Max(newNum - 1, 0);
return newNum; return newNum;
} }
/// <summary>Prüft den Wert auf den gültigen Bereich</summary>
/// <param name="newNum">zu Prüfender Wert</param>
/// <param name="minValue">Minmal erlaubter Wert</param>
/// <param name="maxValue">Maximal erlaubter Wert</param>
/// <returns>Der Wert, wenn er im Bereich liegt, sonst der jeweilige Grenzwert, der überschriten wurde</returns>
public static int ValidateNumber(string newNum, int minValue, int maxValue) public static int ValidateNumber(string newNum, int minValue, int maxValue)
{ {
int num; int num;
if (!int.TryParse(newNum, out num)) if (!int.TryParse(newNum, out num))
return 0; num = 0;
return ValidateNumber(num, minValue, maxValue); return ValidateNumber(num, minValue, maxValue);
} }
/// <summary>Prüft den Wert auf den gültigen Bereich</summary>
/// <param name="newNum">zu Prüfender Wert</param>
/// <param name="minValue">Minmal erlaubter Wert</param>
/// <param name="maxValue">Maximal erlaubter Wert</param>
/// <returns>Der Wert, wenn er im Bereich liegt, sonst der jeweilige Grenzwert, der überschriten wurde</returns>
public static int ValidateNumber(int newNum, int minValue, int maxValue) public static int ValidateNumber(int newNum, int minValue, int maxValue)
{ {
newNum = Math.Max(newNum, minValue); newNum = Math.Max(newNum, minValue);

View file

@ -1,20 +1,29 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using TimeScheduler.Model;
using System.Text;
using System.Threading.Tasks;
namespace TimeScheduler.Model namespace TimeScheduler.Domain
{ {
/// <summary>Schnittstelle zum Provider der die Daten ermitteln</summary> /// <summary>Schnittstelle zum Provider der die Daten ermitteln</summary>
public interface IDomain public interface IDomain
{ {
List<ITimeItem> GetItems(DateTime date); /// <summary>Ermittelt die Werte für den angegebenen Tag</summary>
/// <param name="date">Der Tag für den Werte gesucht werden sollen</param>
/// <returns>Die Daten, für den angefragten Tag</returns>
IEnumerable<ITimeItem> GetItems(DateTime date);
/// <summary>Ermittelt die gültigen Kostenstellen</summary>
/// <returns>Liste der gültigen Kostenstellen</returns>
Dictionary<int, string> GetCostUnits(); Dictionary<int, string> GetCostUnits();
void ElementAdded(ITimeItem timeItem); /// <summary>Fügt ein neues Element hinzu</summary>
/// <param name="timeItem">Das neue Element</param>
int ElementAdded(ITimeItem timeItem);
/// <summary>Verändert ein vorhandenes Element</summary>
/// <param name="timeItem">die neuen Daten</param>
void ElementChanged(ITimeItem timeItem); void ElementChanged(ITimeItem timeItem);
/// <summary>Entfernt ein Element</summary>
/// <param name="timeItem">Das zu entfernende Element</param>
void ElementRemoved(ITimeItem timeItem); void ElementRemoved(ITimeItem timeItem);
} }
} }

View file

@ -4,16 +4,16 @@ using System.IO;
using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Serialization.Formatters.Binary;
using System.Xml.Serialization; using System.Xml.Serialization;
using System.Linq; using System.Linq;
using System.Reflection; using TimeScheduler.Model;
namespace TimeScheduler.Domain.Impl
namespace TimeScheduler.Model.Impl
{ {
class FileDomain : IDomain class FileDomain : IDomain
{ {
#region Konstruktion #region Konstruktion
private List<TimeItem> allItems_ = new List<TimeItem>(); private SimpleTimes allItems_ = new SimpleTimes();
private string filename_ = string.Empty; private string filename_ = string.Empty;
private int lastKey_ = 0;
public FileDomain() public FileDomain()
{ {
@ -25,13 +25,13 @@ namespace TimeScheduler.Model.Impl
else else
{ {
// Wenn nichts vorhanden, dann einen Spielsatz anlegen // Wenn nichts vorhanden, dann einen Spielsatz anlegen
allItems_ = new List<TimeItem> { allItems_.Add(new TimeItem("Desc 01", DateTime.Now.Date.Add(TimeSpan.FromHours(0)), DateTime.Now.Date.Add(TimeSpan.FromHours(1.5)), 11, TimeItemType.Normal, ++lastKey_));
new TimeItem { Description = "Desc 01", From = DateTime.Now.Subtract(TimeSpan.FromHours(2)), Till = DateTime.Now, CostUnit = 14, ItemType = TimeItemType.Normal }, allItems_.Add(new TimeItem("Desc 02", DateTime.Now.Date.Add(TimeSpan.FromHours(2)), DateTime.Now.Date.Add(TimeSpan.FromHours(3.5)), 12, TimeItemType.Break, ++lastKey_));
new TimeItem { Description = "Desc 02", From = DateTime.Now.Subtract(TimeSpan.FromHours(2)), Till = DateTime.Now, CostUnit = 13, ItemType = TimeItemType.Break }, allItems_.Add(new TimeItem("Desc 03", DateTime.Now.Date.Add(TimeSpan.FromHours(4)), DateTime.Now.Date.Add(TimeSpan.FromHours(5.5)), 13, TimeItemType.Holiday, ++lastKey_));
new TimeItem { Description = "Desc 03", From = DateTime.Now.Subtract(TimeSpan.FromHours(2)), Till = DateTime.Now, CostUnit = 12, ItemType = TimeItemType.Holiday }, allItems_.Add(new TimeItem("Desc 04", DateTime.Now.Date.Add(TimeSpan.FromHours(6)), DateTime.Now.Date.Add(TimeSpan.FromHours(7.5)), 14, TimeItemType.Ill, ++lastKey_));
new TimeItem { Description = "Desc 04", From = DateTime.Now.Subtract(TimeSpan.FromHours(2)), Till = DateTime.Now, CostUnit = 11, ItemType = TimeItemType.Ill }, allItems_.Add(new TimeItem("Desc 05", DateTime.Now.Date.Add(TimeSpan.FromHours(8)), DateTime.Now.Date.Add(TimeSpan.FromHours(9.5)), 15, TimeItemType.Normal, ++lastKey_));
new TimeItem { Description = "Desc 05", From = DateTime.Now.Subtract(TimeSpan.FromHours(2)), Till = DateTime.Now, CostUnit = 15, ItemType = TimeItemType.Normal }, // und direkt speichern
}; Save();
} }
} }
#endregion #endregion
@ -41,9 +41,9 @@ namespace TimeScheduler.Model.Impl
{ {
var bin = new BinaryFormatter(); var bin = new BinaryFormatter();
using (var rd = new FileStream(filePath, FileMode.Open)) using (var rd = new FileStream(filePath, FileMode.Open))
allItems_ = bin.Deserialize(rd) as List<TimeItem>; //allItems_ = bin.Deserialize(rd) as List<TimeItem>;
allItems_ = bin.Deserialize(rd) as SimpleTimes;
} }
private void WriteList(string path) private void WriteList(string path)
{ {
var bin = new BinaryFormatter(); var bin = new BinaryFormatter();
@ -53,13 +53,15 @@ namespace TimeScheduler.Model.Impl
private void ReadListXml(string filePath) private void ReadListXml(string filePath)
{ {
var xs = new XmlSerializer(typeof(List<TimeItem>)); //var xs = new XmlSerializer(typeof(List<TimeItem>));
var xs = new XmlSerializer(typeof(SimpleTimes));
using (var rd = new StreamReader(filePath)) using (var rd = new StreamReader(filePath))
allItems_ = xs.Deserialize(rd) as List<TimeItem>; allItems_ = xs.Deserialize(rd) as SimpleTimes;
} }
private void WriteListXml(string path) private void WriteListXml(string path)
{ {
var xs = new XmlSerializer(typeof(List<TimeItem>)); //var xs = new XmlSerializer(typeof(List<TimeItem>));
var xs = new XmlSerializer(typeof(SimpleTimes));
using (StreamWriter wr = new StreamWriter(path)) using (StreamWriter wr = new StreamWriter(path))
xs.Serialize(wr, allItems_); xs.Serialize(wr, allItems_);
} }
@ -67,8 +69,8 @@ namespace TimeScheduler.Model.Impl
private void Load() private void Load()
{ {
ReadListXml(filename_); ReadListXml(filename_);
lastKey_ = allItems_.Max(x => x.Key);
} }
private void Save() private void Save()
{ {
var newFilename = filename_ + ".new"; var newFilename = filename_ + ".new";
@ -79,13 +81,15 @@ namespace TimeScheduler.Model.Impl
#endregion #endregion
#region IDomain #region IDomain
public List<ITimeItem> GetItems(DateTime date) IEnumerable<ITimeItem> IDomain.GetItems(DateTime date)
{ {
var founded = allItems_.Where(x => x.From.Date == date); return allItems_
return founded.Cast<ITimeItem>().ToList(); .Where(x => x.From.Date == date)
.OrderBy(x => x.From)
.Cast<ITimeItem>();
} }
public Dictionary<int, string> GetCostUnits() Dictionary<int, string> IDomain.GetCostUnits()
{ {
return new Dictionary<int, string> return new Dictionary<int, string>
{ {
@ -99,20 +103,23 @@ namespace TimeScheduler.Model.Impl
}; };
} }
public void ElementAdded(ITimeItem timeItem) int IDomain.ElementAdded(ITimeItem timeItem)
{ {
allItems_.Add((TimeItem)timeItem); var ti = new TimeItem(timeItem);
ti.Key = ++lastKey_;
allItems_.Add(ti);
Save();
return ti.Key;
}
void IDomain.ElementChanged(ITimeItem timeItem)
{
allItems_[timeItem.Key].Copy(timeItem);
Save(); Save();
} }
public void ElementChanged(ITimeItem timeItem) void IDomain.ElementRemoved(ITimeItem timeItem)
{ {
allItems_.Remove((TimeItem)timeItem); var removed = allItems_.Remove(timeItem.Key);
allItems_.Add((TimeItem)timeItem); if (removed)
Save();
}
public void ElementRemoved(ITimeItem timeItem)
{
allItems_.Remove((TimeItem)timeItem);
Save(); Save();
} }
#endregion #endregion

View file

@ -0,0 +1,90 @@
using System;
using System.Collections.ObjectModel;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
namespace TimeScheduler.Domain.Impl
{
/// <summary>Einfache Liste für die TimeItems</summary>
/// <remarks>
/// Implementierung der Schittstelle für die Xml-Serialisierung, weil es sonst zu Schlüsseln Fehler kommt.
/// Implementierung von: http://weblogs.asp.net/pwelter34/444961
/// </remarks>
[Serializable]
[XmlRoot("SimpleTimes")]
public class SimpleTimes : KeyedCollection<int, TimeItem>, IXmlSerializable
{
#region Konstruktor
/// <summary>Konstruktor</summary>
public SimpleTimes() { }
/// <inheritdoc/>
protected override int GetKeyForItem(TimeItem item) { return item.Key; }
#endregion
#region IXmlSerializable
/// <summary>Schema ermitteln</summary>
/// <returns><c>null</c> im Standard</returns>
public XmlSchema GetSchema() { return null; }
/// <summary>Liest die Elemente aus dem XML-Stream</summary>
/// <param name="reader">Der Steam-Leser</param>
public void ReadXml(XmlReader reader)
{
//var keySerializer = new XmlSerializer(typeof(int));
var valueSerializer = new XmlSerializer(typeof(TimeItem));
var wasEmpty = reader.IsEmptyElement;
reader.Read();
if (wasEmpty)
return;
while (reader.NodeType != XmlNodeType.EndElement)
{
reader.ReadStartElement("item");
//reader.ReadStartElement("key");
//var key = (int)keySerializer.Deserialize(reader);
//reader.ReadEndElement();
reader.ReadStartElement("value");
var value = (TimeItem)valueSerializer.Deserialize(reader);
reader.ReadEndElement();
Add(value);
reader.ReadEndElement();
reader.MoveToContent();
}
reader.ReadEndElement();
}
/// <summary>Schreibt die Elemente in den XML-Stream</summary>
/// <param name="writer">Der Stream-Schreiber</param>
public void WriteXml(XmlWriter writer)
{
//var keySerializer = new XmlSerializer(typeof(int));
var valueSerializer = new XmlSerializer(typeof(TimeItem));
foreach (var key in Dictionary.Keys)
{
writer.WriteStartElement("item");
//writer.WriteStartElement("key");
//keySerializer.Serialize(writer, key);
//writer.WriteEndElement();
writer.WriteStartElement("value");
var value = this[key];
valueSerializer.Serialize(writer, value);
writer.WriteEndElement();
writer.WriteEndElement();
}
}
#endregion
}
}

View file

@ -1,12 +1,11 @@
using System; using System;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using TimeScheduler.Common; using TimeScheduler.Common;
using TimeScheduler.Model;
namespace TimeScheduler.Model.Impl namespace TimeScheduler.Domain.Impl
{ {
/// <summary> /// <summary>Beinhaltet den Datenbestand eines Zeitelementes</summary>
///
/// </summary>
/// <remarks> /// <remarks>
/// <see cref="ISerializable"/> muss implementiert werden, damit die Daten über den BinarFormater serialisiert werden können. /// <see cref="ISerializable"/> muss implementiert werden, damit die Daten über den BinarFormater serialisiert werden können.
/// Für den XmlSerializer müsste die Klasse auf Public gestellt werden, was nicht immer gewünscht ist /// Für den XmlSerializer müsste die Klasse auf Public gestellt werden, was nicht immer gewünscht ist
@ -14,7 +13,32 @@ namespace TimeScheduler.Model.Impl
[Serializable] [Serializable]
public class TimeItem : NotifyableObject, ITimeItem//, ISerializable public class TimeItem : NotifyableObject, ITimeItem//, ISerializable
{ {
public TimeItem() { } #region Konstruktion
/// <summary>Standard-Konstruktor</summary>
public TimeItem() { key_ = -1; }
/// <summary>Konstruktor</summary>
/// <param name="description">Beschreibung</param>
/// <param name="from">Von</param>
/// <param name="till">Bis</param>
/// <param name="costUnit">Kostenstelle</param>
/// <param name="itemType">Elementtyp</param>
/// <param name="key">Schlüssel</param>
public TimeItem(string description, DateTime from, DateTime till, int costUnit, TimeItemType itemType, int? key = null) : this()
{
description_ = description;
from_ = from;
till_ = till;
costUnit_ = costUnit;
itemType_ = itemType;
if (key.HasValue)
key_ = key.Value;
}
/// <summary>Kopier-Konstruktor</summary>
/// <param name="rhs">Element von dem kopiert wird</param>
public TimeItem(ITimeItem rhs) { Copy(rhs); Key = rhs.Key; }
#endregion
//#region ISerializable //#region ISerializable
//public TimeItem(SerializationInfo info, StreamingContext context) //public TimeItem(SerializationInfo info, StreamingContext context)
@ -27,20 +51,42 @@ namespace TimeScheduler.Model.Impl
//} //}
//#endregion //#endregion
#region Methoden
/// <summary>Kopiert die Werte der Eigenschaften auf diese Objekt, ohney Key</summary>
/// <param name="rhs">Objkt von em kopiert werden soll</param>
public void Copy(ITimeItem rhs)
{
Description = rhs.Description;
From = rhs.From;
Till = rhs.Till;
CostUnit = rhs.CostUnit;
ItemType = rhs.ItemType;
}
#endregion
#region ITimeItem #region ITimeItem
private int key_;
/// <inheritdoc/>
public int Key { get { return key_; } set { SetField(ref key_, value); } }
private string description_; private string description_;
/// <inheritdoc/>
public string Description { get { return description_; } set { SetField(ref description_, value); } } public string Description { get { return description_; } set { SetField(ref description_, value); } }
private DateTime from_; private DateTime from_;
/// <inheritdoc/>
public DateTime From { get { return from_; } set { SetField(ref from_, value); } } public DateTime From { get { return from_; } set { SetField(ref from_, value); } }
private DateTime till_; private DateTime till_;
/// <inheritdoc/>
public DateTime Till { get { return till_; } set { SetField(ref till_, value); } } public DateTime Till { get { return till_; } set { SetField(ref till_, value); } }
private int costUnit_; private int costUnit_;
/// <inheritdoc/>
public int CostUnit { get { return costUnit_; } set { SetField(ref costUnit_, value); } } public int CostUnit { get { return costUnit_; } set { SetField(ref costUnit_, value); } }
private TimeItemType itemType_; private TimeItemType itemType_;
/// <inheritdoc/>
public TimeItemType ItemType { get { return itemType_; } set { SetField(ref itemType_, value); } } public TimeItemType ItemType { get { return itemType_; } set { SetField(ref itemType_, value); } }
#endregion #endregion
} }

View file

@ -6,7 +6,7 @@
xmlns:local="clr-namespace:TimeScheduler" xmlns:local="clr-namespace:TimeScheduler"
xmlns:c="clr-namespace:TimeScheduler.Common" xmlns:c="clr-namespace:TimeScheduler.Common"
xmlns:vm="clr-namespace:TimeScheduler.ViewModel" xmlns:vm="clr-namespace:TimeScheduler.ViewModel"
xmlns:domain="clr-namespace:TimeScheduler.Model.Impl" xmlns:domain="clr-namespace:TimeScheduler.Domain.Impl"
mc:Ignorable="d" Language="de" mc:Ignorable="d" Language="de"
Title="TimeSchedule" Height="350" Width="525"> Title="TimeSchedule" Height="350" Width="525">
<Window.DataContext> <Window.DataContext>
@ -27,8 +27,7 @@
<DockPanel Grid.Column="0"> <DockPanel Grid.Column="0">
<DatePicker DockPanel.Dock="Top" Margin="5" SelectedDate="{Binding Path=CurrentDate}"/> <DatePicker DockPanel.Dock="Top" Margin="5" SelectedDate="{Binding Path=CurrentDate}"/>
<ListBox x:Name="lbTimeElements" Margin="5" HorizontalContentAlignment="Stretch" <ListBox x:Name="lbTimeElements" Margin="5" HorizontalContentAlignment="Stretch"
ItemsSource="{Binding TimeItems}" SelectedItem="{Binding SelectedTimeItem}" ItemsSource="{Binding TimeItems}" SelectedItem="{Binding SelectedTimeItem}">
>
<ListBox.ItemContainerStyle> <ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem"> <Style TargetType="ListBoxItem">
<Setter Property="Background"> <Setter Property="Background">

View file

@ -6,6 +6,9 @@ namespace TimeScheduler.Model
/// <summary>Beinhaltet die Definition eines Daten-Elementes, das eine Zeiteinheit aufnimmt</summary> /// <summary>Beinhaltet die Definition eines Daten-Elementes, das eine Zeiteinheit aufnimmt</summary>
public interface ITimeItem : INotifyPropertyChanged public interface ITimeItem : INotifyPropertyChanged
{ {
/// <summary>Eindeutiger Schlüssel, der ein Element identifizieren kann</summary>
int Key { get; set; }
/// <summary>Textuelle Beschreibung</summary> /// <summary>Textuelle Beschreibung</summary>
string Description { get; set; } string Description { get; set; }

View file

@ -1,71 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Dieser Code wurde von einem Tool generiert.
// Laufzeitversion: 4.0.30319.42000
//
// Änderungen an dieser Datei können fehlerhaftes Verhalten verursachen und gehen verloren, wenn
// der Code neu generiert wird.
// </auto-generated>
//------------------------------------------------------------------------------
namespace TimeScheduler.Properties
{
/// <summary>
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
/// </summary>
// Diese Klasse wurde von der StronglyTypedResourceBuilder-Klasse
// über ein Tool wie ResGen oder Visual Studio automatisch generiert.
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
// mit der Option /str erneut aus, oder erstellen Sie Ihr VS-Projekt neu.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.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>
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TimeScheduler.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
/// Ressourcenlookups, die diese stark typisierte Ressourcenklasse verwenden.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

View file

@ -1,117 +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.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: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" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</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" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</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=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View file

@ -1,30 +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 TimeScheduler.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}

View file

@ -1,7 +0,0 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View file

@ -24,6 +24,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\TimeScheduler.XML</DocumentationFile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
@ -33,6 +34,7 @@
<DefineConstants>TRACE</DefineConstants> <DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\TimeScheduler.XML</DocumentationFile>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
@ -60,6 +62,7 @@
<Compile Include="Domain\IDomain.cs" /> <Compile Include="Domain\IDomain.cs" />
<Compile Include="Domain\Impl\FileDomain.cs" /> <Compile Include="Domain\Impl\FileDomain.cs" />
<Compile Include="Domain\Impl\TimeItem.cs" /> <Compile Include="Domain\Impl\TimeItem.cs" />
<Compile Include="Domain\Impl\SimpleTimes.cs" />
<Compile Include="Domain\TimeItemType.cs" /> <Compile Include="Domain\TimeItemType.cs" />
<Compile Include="Model\ITimeItem.cs" /> <Compile Include="Model\ITimeItem.cs" />
<Compile Include="ViewModel\MainViewModel.cs" /> <Compile Include="ViewModel\MainViewModel.cs" />
@ -82,24 +85,6 @@
<Compile Include="Properties\AssemblyInfo.cs"> <Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<AppDesigner Include="Properties\" /> <AppDesigner Include="Properties\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -2,10 +2,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input; using System.Windows.Input;
using TimeScheduler.Common; using TimeScheduler.Common;
using TimeScheduler.Domain;
using TimeScheduler.Model; using TimeScheduler.Model;
namespace TimeScheduler.ViewModel namespace TimeScheduler.ViewModel
@ -13,9 +12,8 @@ namespace TimeScheduler.ViewModel
class MainViewModel : NotifyableObject class MainViewModel : NotifyableObject
{ {
#region Konstruktion #region Konstruktion
private bool inLoading_ = false;
/// <summary>Standard-Konstruktor</summary> /// <summary>Standard-Konstruktor</summary>
public MainViewModel() : this(new Model.Impl.FileDomain()) { Refresh(); } public MainViewModel() : this(new Domain.Impl.FileDomain()) { Refresh(); }
/// <summary>Konstruktor</summary> /// <summary>Konstruktor</summary>
/// <param name="provider"></param> /// <param name="provider"></param>
@ -29,6 +27,7 @@ namespace TimeScheduler.ViewModel
CreateCommands(); CreateCommands();
} }
/// <summary>Datenbeschaffer</summary>
protected IDomain Provider { get; private set; } protected IDomain Provider { get; private set; }
#endregion #endregion
@ -86,9 +85,16 @@ namespace TimeScheduler.ViewModel
// Laufende Datein belegen // Laufende Datein belegen
var items = Provider.GetItems(date); var items = Provider.GetItems(date);
// Event abhängen, damit keine Änderungen an den Provider geschickt werden
TimeItems.CollectionChanged -= TimeItems_CollectionChanged;
try try
{ {
inLoading_ = true; // Event der Objekte entfernen
foreach (var item in TimeItems)
item.PropertyChanged -= Item_PropertyChanged;
// Elemente umlagern
TimeItems.Clear(); TimeItems.Clear();
foreach (var item in items) foreach (var item in items)
{ {
@ -96,7 +102,11 @@ namespace TimeScheduler.ViewModel
TimeItems.Add(item); TimeItems.Add(item);
} }
} }
finally { inLoading_ = false; } finally
{
// Event wieder anhängen
TimeItems.CollectionChanged += TimeItems_CollectionChanged;
}
SelectedTimeItem = TimeItems.FirstOrDefault(); SelectedTimeItem = TimeItems.FirstOrDefault();
} }
@ -108,7 +118,7 @@ namespace TimeScheduler.ViewModel
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add) if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{ {
foreach (ITimeItem item in e.NewItems) foreach (ITimeItem item in e.NewItems)
Provider.ElementAdded(item); item.Key = Provider.ElementAdded(item);
} }
else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove) else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
{ {