diff --git a/MultiTerm.Core/ViewModel/DataViewModel.cs b/MultiTerm.Core/ViewModel/CharacterDataViewModel.cs
similarity index 51%
rename from MultiTerm.Core/ViewModel/DataViewModel.cs
rename to MultiTerm.Core/ViewModel/CharacterDataViewModel.cs
index c3e5c8c..59f9d1e 100644
--- a/MultiTerm.Core/ViewModel/DataViewModel.cs
+++ b/MultiTerm.Core/ViewModel/CharacterDataViewModel.cs
@@ -3,45 +3,44 @@ using MultiTerm.Protocols.Model;
namespace MultiTerm.Core.ViewModel;
-public partial class DataViewModel : ObservableObject
+public partial class CharacterDataViewModel : ObservableObject, IDataViewModel
{
///
- /// Identifier for the frontend to group lines.
+ /// Object of data model.
///
+ private readonly ExtendedChar character;
+
+ #region IDataViewModel Implementation
+
[ObservableProperty]
private int lineIdentifier;
- ///
- /// Object of data model.
- ///
[ObservableProperty]
- private ExtendedChar character;
+ private TimeOnly time;
- ///
- /// Property that hosts a displayable string of the character (UTF-16 encoded).
- ///
[ObservableProperty]
- private string displayStringUtf16 = String.Empty;
+ private string displayString = String.Empty;
- ///
- /// Property that hosts a string of the character (hexadecimal format).
- ///
[ObservableProperty]
private string displayStringHex = String.Empty;
- ///
- /// Property that hosts a string of the character (binary format).
- ///
[ObservableProperty]
private string displayStringBin = String.Empty;
+ #endregion
+
+ ///
+ /// Allows access to character of this instance.
+ ///
+ public char Character { get { return this.character.Character; } }
- public DataViewModel(ExtendedChar character, int lineIdentifier)
+ public CharacterDataViewModel(ExtendedChar character, int lineIdentifier)
{
this.character = character;
this.lineIdentifier = lineIdentifier;
- this.DisplayStringUtf16 = character.ToUtf16String();
+ this.DisplayString = character.ToUtf16String();
this.DisplayStringHex = character.ToHexString();
this.DisplayStringBin = character.ToBinaryString();
+ this.Time = character.Time;
}
}
diff --git a/MultiTerm.Core/ViewModel/CommunicationDataViewModel.cs b/MultiTerm.Core/ViewModel/CommunicationDataViewModel.cs
index 2289604..81e96ba 100644
--- a/MultiTerm.Core/ViewModel/CommunicationDataViewModel.cs
+++ b/MultiTerm.Core/ViewModel/CommunicationDataViewModel.cs
@@ -1,146 +1,111 @@
using Common;
using Common.Helpers;
using CommunityToolkit.Mvvm.ComponentModel;
-using CommunityToolkit.Mvvm.Input;
using MultiTerm.Core.Types;
-using MultiTerm.Protocols;
using MultiTerm.Protocols.Model;
using System.Collections.ObjectModel;
-
namespace MultiTerm.Core.ViewModel;
-public partial class CommunicationDataViewModel : ObservableObject
+public partial class CommunicationDataViewModel : ObservableObject, ICommunicationDataViewModel
{
- private ICommunicationProtocol? communicationProtocol;
private readonly IContext uiContext;
- private NewlineSeparatorType currentReceiveNewlineSeparatorType = NewlineSeparatorType.None;
- private NewlineSeparatorType currentSentNewlineSeparatorType = NewlineSeparatorType.None;
- ///
- /// Represents the collection of received characters from a communication protocol.
- ///
- [ObservableProperty]
- private ObservableCollection receivedData = new();
+ private int dataCharacterCount = 0;
+ private List? listOfPreviousCharacters = null;
- ///
- /// Represents the collection of the selection of received characters.
- ///
+ #region ICommunicationDataViewModel Implementation
+
+ [ObservableProperty]
+ private ObservableCollection data = new();
+
[ObservableProperty]
- private List? selectedReceivedData;
+ private string dataAsString = string.Empty;
- ///
- /// Represents the collection of sent characters to a communication protocol.
- ///
[ObservableProperty]
- private ObservableCollection sentData = new();
+ private ObservableCollection? selected = new();
- ///
- /// Represents the collection of the selection of sent characters.
- ///
[ObservableProperty]
- private List? selectedSentData;
+ NewlineSeparatorType newlineSeparator = NewlineSeparatorType.None;
- public CommunicationDataViewModel(ICommunicationProtocol? communicationProtocol, IContext context)
+ #endregion
+
+
+ public CommunicationDataViewModel(IContext context)
{
this.uiContext = context;
- this.communicationProtocol = communicationProtocol;
- if (this.communicationProtocol != null)
- {
- this.communicationProtocol.ReceivedDataEvent += CommunicationProtocol_ReceivedDataEvent;
- this.communicationProtocol.SentDataEvent += CommunicationProtocol_SentDataEvent;
- }
- else // TEMP
- {
- //string exampleData = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Pellentesque elit eget gravida cum sociis natoque penatibus et magnis. Purus sit amet volutpat consequat mauris nunc congue nisi vitae. Id ornare arcu odio ut sem. Neque ornare aenean euismod elementum nisi quis eleifend. Faucibus vitae aliquet nec ullamcorper sit. Fermentum iaculis eu non diam phasellus vestibulum lorem sed risus. Pellentesque nec nam aliquam sem et tortor consequat id porta. Diam sollicitudin tempor id eu nisl. Fames ac turpis egestas sed tempus urna et. Commodo odio aenean sed adipiscing diam donec adipiscing tristique risus. Id aliquet lectus proin nibh nisl condimentum id. Dolor sit amet consectetur adipiscing elit duis. Sed vulputate odio ut enim blandit. Neque convallis a cras semper auctor neque vitae.\r\n\r\nLacus laoreet non curabitur gravida arcu ac tortor. Volutpat maecenas volutpat blandit aliquam. Neque laoreet suspendisse interdum consectetur. Tincidunt augue interdum velit euismod in pellentesque massa placerat. Magna fringilla urna porttitor rhoncus dolor purus non enim praesent. Fermentum leo vel orci porta non pulvinar neque laoreet suspendisse. Scelerisque viverra mauris in aliquam sem fringilla. Nec feugiat nisl pretium fusce id velit ut. Urna cursus eget nunc scelerisque viverra mauris. Condimentum mattis pellentesque id nibh tortor id aliquet. Enim sed faucibus turpis in eu. Adipiscing elit pellentesque habitant morbi tristique. A pellentesque sit amet porttitor eget dolor morbi non arcu. Amet commodo nulla facilisi nullam vehicula ipsum a arcu. Hac habitasse platea dictumst vestibulum rhoncus est pellentesque elit ullamcorper. Curabitur vitae nunc sed velit dignissim sodales ut. Malesuada fames ac turpis egestas maecenas pharetra. Tellus pellentesque eu tincidunt tortor aliquam.\r\n\r\nVitae proin sagittis nisl rhoncus mattis rhoncus urna neque viverra. Eget mi proin sed libero enim sed faucibus. Commodo nulla facilisi nullam vehicula ipsum. Proin libero nunc consequat interdum varius sit amet mattis vulputate. Morbi tristique senectus et netus. Feugiat scelerisque varius morbi enim nunc. Nulla aliquet enim tortor at auctor urna nunc. Non pulvinar neque laoreet suspendisse interdum consectetur libero id. Tellus orci ac auctor augue mauris augue neque gravida in. In egestas erat imperdiet sed euismod. Amet volutpat consequat mauris nunc congue nisi. Massa eget egestas purus viverra accumsan in. Eget duis at tellus at. Mi sit amet mauris commodo quis imperdiet. Nibh mauris cursus mattis molestie a iaculis at.\r\n\r\nNetus et malesuada fames ac turpis. Sit amet dictum sit amet justo donec. Euismod quis viverra nibh cras pulvinar mattis. Sit amet commodo nulla facilisi nullam vehicula ipsum a arcu. Scelerisque felis imperdiet proin fermentum. Ac tincidunt vitae semper quis lectus nulla at. Sit amet commodo nulla facilisi nullam vehicula. Enim lobortis scelerisque fermentum dui faucibus in ornare quam. Quam id leo in vitae turpis massa sed. Quam quisque id diam vel quam. A condimentum vitae sapien pellentesque. Neque aliquam vestibulum morbi blandit cursus risus at. Velit laoreet id donec ultrices tincidunt arcu non sodales neque. Tempus imperdiet nulla malesuada pellentesque elit eget gravida cum sociis. Egestas tellus rutrum tellus pellentesque eu tincidunt tortor. Nec feugiat in fermentum posuere. Dui accumsan sit amet nulla. Lacus viverra vitae congue eu consequat ac felis. Etiam tempor orci eu lobortis. Fermentum leo vel orci porta non pulvinar.";
- string exampleData = "\r\nUnicode Latin Letter D: \u018A\n--------------------------------------------------------------\r\nSPLITFLAP\r\n--------------------------------------------------------------\r\nMcuShell ; Group of McuShell commands\r\n help|status ; Print help or status information\r\nSplitFlap ; Group of McuRTOS commands\r\n help ; Print help or status information\r\n setId ; sets the position (setupId) of the sf and its id (hwId)\r\n initAll ; init all Splitflaps\r\n Display ; displays as many chars of the string as sf are available\r\n addId ; add new hwId with offset\r\nMcuRTOS ; Group of McuRTOS commands\r\n help|status ; Print help or status information\r\n tasklist ; Print tasklist\r\nMcuFlash ; Group of flash ini commands\r\n help|status ; Print help or status information\r\n dump ; Dump memory data\r\n erase ; Erase memory at address\r\nini ; Group of flash ini commands\r\n help|status ; Print help or status information\r\n dump ; Dump data information\r\n erase ; Erase data information\r\nMcuMinINI ; Group of McuMinINI commands\r\n help|status ; Print help or status information\r\n read ; Read a key from a section in a file\r\n write ; Write a key with value to a section in a file\r\n delkey ; Delete a key in a section of file\r\n delsec ; Delete a section in a file\r\nnvmc ; Group of NVMC commands\r\n help|status ; Print help or status information\r\n flags ; Set flags\r\nrs ; Group of RS-485 commands\r\n help|status ; Print help or status information\r\n addr ; Set RS-485 address\r\n send ; Send a text to the RS-485 bus\r\n sendcmd ; Send a shell command to the RS-485 address and check response\r\n log on|off ; Log RS-485 bus activity to McuLog\r\nMcuUart485 ; Group of RS-485 commands\r\n help|status ; Print help or status information\r\n clear ; Clear UART ISR flags\r\n\r\nCMD>";
- //string exampleData = "This is some example Text\nSecond line\nNow a very long line: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
- int counter = 0;
- int lineNumber = 1;
- //List listOfChars = new();
- foreach (var character in exampleData)
- {
- if(++counter > 100 || character == '\n')
- {
- //this.ReceivedData.Add();
- //listOfChars = new List();
- counter = 0;
- lineNumber += 1;
- }
- var extdChar = new ExtendedChar(character);
- //listOfChars.Add(extdChar);
- this.ReceivedData.Add(new DataViewModel(extdChar, lineNumber));
- }
- }
+ // TEMP
+ //{
+ // //string exampleData = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Pellentesque elit eget gravida cum sociis natoque penatibus et magnis. Purus sit amet volutpat consequat mauris nunc congue nisi vitae. Id ornare arcu odio ut sem. Neque ornare aenean euismod elementum nisi quis eleifend. Faucibus vitae aliquet nec ullamcorper sit. Fermentum iaculis eu non diam phasellus vestibulum lorem sed risus. Pellentesque nec nam aliquam sem et tortor consequat id porta. Diam sollicitudin tempor id eu nisl. Fames ac turpis egestas sed tempus urna et. Commodo odio aenean sed adipiscing diam donec adipiscing tristique risus. Id aliquet lectus proin nibh nisl condimentum id. Dolor sit amet consectetur adipiscing elit duis. Sed vulputate odio ut enim blandit. Neque convallis a cras semper auctor neque vitae.\r\n\r\nLacus laoreet non curabitur gravida arcu ac tortor. Volutpat maecenas volutpat blandit aliquam. Neque laoreet suspendisse interdum consectetur. Tincidunt augue interdum velit euismod in pellentesque massa placerat. Magna fringilla urna porttitor rhoncus dolor purus non enim praesent. Fermentum leo vel orci porta non pulvinar neque laoreet suspendisse. Scelerisque viverra mauris in aliquam sem fringilla. Nec feugiat nisl pretium fusce id velit ut. Urna cursus eget nunc scelerisque viverra mauris. Condimentum mattis pellentesque id nibh tortor id aliquet. Enim sed faucibus turpis in eu. Adipiscing elit pellentesque habitant morbi tristique. A pellentesque sit amet porttitor eget dolor morbi non arcu. Amet commodo nulla facilisi nullam vehicula ipsum a arcu. Hac habitasse platea dictumst vestibulum rhoncus est pellentesque elit ullamcorper. Curabitur vitae nunc sed velit dignissim sodales ut. Malesuada fames ac turpis egestas maecenas pharetra. Tellus pellentesque eu tincidunt tortor aliquam.\r\n\r\nVitae proin sagittis nisl rhoncus mattis rhoncus urna neque viverra. Eget mi proin sed libero enim sed faucibus. Commodo nulla facilisi nullam vehicula ipsum. Proin libero nunc consequat interdum varius sit amet mattis vulputate. Morbi tristique senectus et netus. Feugiat scelerisque varius morbi enim nunc. Nulla aliquet enim tortor at auctor urna nunc. Non pulvinar neque laoreet suspendisse interdum consectetur libero id. Tellus orci ac auctor augue mauris augue neque gravida in. In egestas erat imperdiet sed euismod. Amet volutpat consequat mauris nunc congue nisi. Massa eget egestas purus viverra accumsan in. Eget duis at tellus at. Mi sit amet mauris commodo quis imperdiet. Nibh mauris cursus mattis molestie a iaculis at.\r\n\r\nNetus et malesuada fames ac turpis. Sit amet dictum sit amet justo donec. Euismod quis viverra nibh cras pulvinar mattis. Sit amet commodo nulla facilisi nullam vehicula ipsum a arcu. Scelerisque felis imperdiet proin fermentum. Ac tincidunt vitae semper quis lectus nulla at. Sit amet commodo nulla facilisi nullam vehicula. Enim lobortis scelerisque fermentum dui faucibus in ornare quam. Quam id leo in vitae turpis massa sed. Quam quisque id diam vel quam. A condimentum vitae sapien pellentesque. Neque aliquam vestibulum morbi blandit cursus risus at. Velit laoreet id donec ultrices tincidunt arcu non sodales neque. Tempus imperdiet nulla malesuada pellentesque elit eget gravida cum sociis. Egestas tellus rutrum tellus pellentesque eu tincidunt tortor. Nec feugiat in fermentum posuere. Dui accumsan sit amet nulla. Lacus viverra vitae congue eu consequat ac felis. Etiam tempor orci eu lobortis. Fermentum leo vel orci porta non pulvinar.";
+ // string exampleData = "\r\nUnicode Latin Letter D: \u018A\n--------------------------------------------------------------\r\nSPLITFLAP\r\n--------------------------------------------------------------\r\nMcuShell ; Group of McuShell commands\r\n help|status ; Print help or status information\r\nSplitFlap ; Group of McuRTOS commands\r\n help ; Print help or status information\r\n setId ; sets the position (setupId) of the sf and its id (hwId)\r\n initAll ; init all Splitflaps\r\n Display ; displays as many chars of the string as sf are available\r\n addId ; add new hwId with offset\r\nMcuRTOS ; Group of McuRTOS commands\r\n help|status ; Print help or status information\r\n tasklist ; Print tasklist\r\nMcuFlash ; Group of flash ini commands\r\n help|status ; Print help or status information\r\n dump ; Dump memory data\r\n erase ; Erase memory at address\r\nini ; Group of flash ini commands\r\n help|status ; Print help or status information\r\n dump ; Dump data information\r\n erase ; Erase data information\r\nMcuMinINI ; Group of McuMinINI commands\r\n help|status ; Print help or status information\r\n read ; Read a key from a section in a file\r\n write ; Write a key with value to a section in a file\r\n delkey ; Delete a key in a section of file\r\n delsec ; Delete a section in a file\r\nnvmc ; Group of NVMC commands\r\n help|status ; Print help or status information\r\n flags ; Set flags\r\nrs ; Group of RS-485 commands\r\n help|status ; Print help or status information\r\n addr ; Set RS-485 address\r\n send ; Send a text to the RS-485 bus\r\n sendcmd ; Send a shell command to the RS-485 address and check response\r\n log on|off ; Log RS-485 bus activity to McuLog\r\nMcuUart485 ; Group of RS-485 commands\r\n help|status ; Print help or status information\r\n clear ; Clear UART ISR flags\r\n\r\nCMD>";
+ // //string exampleData = "This is some example Text\nSecond line\nNow a very long line: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
+ // int counter = 0;
+ // int lineNumber = 1;
+ // //List listOfChars = new();
+ // foreach (var character in exampleData)
+ // {
+ // if(++counter > 100 || character == '\n')
+ // {
+ // //this.ReceivedData.Add();
+ // //listOfChars = new List();
+ // counter = 0;
+ // lineNumber += 1;
+ // }
+ // var extdChar = new ExtendedChar(character);
+ // //listOfChars.Add(extdChar);
+ // this.ReceivedData.Add(new DataViewModel(extdChar, lineNumber));
+ // }
+ //}
}
- ~CommunicationDataViewModel()
+ public void HandleNewData(IEnumerable newRawData)
{
- if (this.communicationProtocol != null)
- {
- this.communicationProtocol.ReceivedDataEvent -= CommunicationProtocol_ReceivedDataEvent;
- this.communicationProtocol.SentDataEvent -= CommunicationProtocol_SentDataEvent;
- this.communicationProtocol = null;
- }
+ // update collection and string, invoke ui thread if necessary
+ ContextHelpers.InvokeIfNecessary(this.uiContext, (Action)delegate
+ {
+ InsertNewNewCharactersIntoCollection(this.Data, ref this.dataCharacterCount, ref this.listOfPreviousCharacters, this.NewlineSeparator, newRawData);
+ this.DataAsString = InsertNewCharactersIntoString(this.DataAsString, newRawData);
+ });
}
///
- /// Overwrites local variables for current newline separators and triggers recration of datacollections according to new newline separators (only if they changed).
+ /// After changing the newline separator, the data needs to be reordered.
///
- /// new receive newline separator type or null
- /// new send newline separator type or null
- public void ConfigureNewlineSeparators(NewlineSeparatorType? receiveNewlineSeparatorType, NewlineSeparatorType? sendNewlineSeparatorType)
+ partial void OnNewlineSeparatorChanged(NewlineSeparatorType value)
{
- if (receiveNewlineSeparatorType != null)
+ // update collection, invoke ui thread if necessary
+ ContextHelpers.InvokeIfNecessary(this.uiContext, (Action)delegate
{
- // if it is the same as the current newline separator type => ignore
- if(receiveNewlineSeparatorType == this.currentReceiveNewlineSeparatorType) { return; }
-
- // set new newline separator type and overwrite data collection (triggers property changed)
- this.currentReceiveNewlineSeparatorType = (NewlineSeparatorType)receiveNewlineSeparatorType;
- // update collection, invoke ui thread if necessary
- ContextHelpers.InvokeIfNecessary(this.uiContext, (Action)delegate
- {
- this.ReceivedData = ReorderDataCollection(this.ReceivedData, this.currentReceiveNewlineSeparatorType);
- });
- }
- if (sendNewlineSeparatorType != null)
- {
- // if it is the same as the current newline separator type => ignore
- if (sendNewlineSeparatorType == this.currentSentNewlineSeparatorType) { return; }
-
- // set new newline separator type and overwrite data collection (triggers property changed)
- this.currentSentNewlineSeparatorType = (NewlineSeparatorType)sendNewlineSeparatorType;
- // update collection, invoke ui thread if necessary
- ContextHelpers.InvokeIfNecessary(this.uiContext, (Action)delegate
- {
- this.SentData = ReorderDataCollection(this.SentData, this.currentSentNewlineSeparatorType);
- });
- }
+ this.Data = ReorderCollection(this.Data, value);
+ this.DataAsString = ReorderString(this.Data, value);
+ });
}
+ #region Collection Manipulation
///
- /// Function that reorders a given collection using the given .
+ /// Function that reorders a given collection with item type using the given .
/// Reordered collection is returned, but LineIdentifier is also overwritten in the parameter.
///
/// items in this collection will be reordered
/// separator between lines
/// reordered collection
- private static ObservableCollection ReorderDataCollection(ObservableCollection currentCollection, NewlineSeparatorType newlineSeparatorType)
+ private static ObservableCollection ReorderCollection(ObservableCollection currentCollection, NewlineSeparatorType newlineSeparatorType)
{
- ObservableCollection newCollection = new();
+ ObservableCollection newCollection = new();
int lineCounter = 0;
List? previousCharacters = null;
- foreach (var item in currentCollection)
+ // iterate through items
+ foreach (CharacterDataViewModel item in currentCollection)
{
item.LineIdentifier = lineCounter;
newCollection.Add(item);
- switch (ShouldIntroduceNewlineAfterThisCharacter(item.Character.Character, previousCharacters, newlineSeparatorType))
+
+ switch (ShouldIntroduceNewlineAfterThisCharacter(item.Character, previousCharacters, newlineSeparatorType))
{
case IntroduceNewlineAfterThisCharacterResult.NoNewline:
// a decision could be made, previousCharacters can be cleared
- if(previousCharacters != null) { previousCharacters = null; }
+ if (previousCharacters != null) { previousCharacters = null; }
// nothing to do
break;
@@ -155,17 +120,69 @@ public partial class CommunicationDataViewModel : ObservableObject
// first time that more characters are required => create new list
previousCharacters ??= new List();
// add current character to list
- previousCharacters.Add(item.Character.Character);
+ previousCharacters.Add(item.Character);
break;
default:
- throw new Exception($"'{nameof(ReorderDataCollection)}()' failed because of error when checking if a newline should be introduced.");
+ throw new Exception($"'{nameof(ReorderCollection)}()' failed because of error when checking if a newline should be introduced.");
}
}
-
+
return newCollection;
}
+ ///
+ /// Function that handles a collection of new characters that should end up in the collection .
+ /// In case a new line is required, according to the given , it is automatically introduced.
+ /// Following parameters need to be referenced and stored outside: and .
+ ///
+ /// collection to add the characters to
+ /// current line count
+ /// list of previous character, newest at the last position of the list, null if nothing is stored
+ /// separator between seperate lines
+ /// characters to add to the
+ /// in case of any error
+ private static void InsertNewNewCharactersIntoCollection(ObservableCollection dataCollection,
+ ref int collectionLineCounter,
+ ref List? previousCharacters,
+ NewlineSeparatorType newlineSeparatorType,
+ IEnumerable newCharacters)
+ {
+ // go through every character
+ foreach (var newExtdChar in newCharacters)
+ {
+ // add to collection with the current counter, invoking UI context if necssary
+ var currentLineCounter = collectionLineCounter;
+ dataCollection.Add(new CharacterDataViewModel(newExtdChar, currentLineCounter));
+
+ switch (ShouldIntroduceNewlineAfterThisCharacter(newExtdChar.Character, previousCharacters, newlineSeparatorType))
+ {
+ case IntroduceNewlineAfterThisCharacterResult.NoNewline:
+ // a decision could be made, previousCharacters can be cleared
+ if (previousCharacters != null) { previousCharacters = null; }
+ // nothing to do
+ break;
+
+ case IntroduceNewlineAfterThisCharacterResult.IntroduceNewline:
+ // a decision could be made, previousCharacters can be cleared
+ if (previousCharacters != null) { previousCharacters = null; }
+ // increase line count and break
+ collectionLineCounter++;
+ break;
+
+ case IntroduceNewlineAfterThisCharacterResult.RequiresMoreCharacters:
+ // first time that more characters are required => create new list
+ previousCharacters ??= new List();
+ // add current character to list
+ previousCharacters.Add(newExtdChar.Character);
+ break;
+
+ default:
+ throw new Exception($"'{nameof(InsertNewNewCharactersIntoCollection)}()' failed because of error when checking if a newline should be introduced.");
+ }
+ }
+ }
+
///
/// Result type for
///
@@ -206,7 +223,7 @@ public partial class CommunicationDataViewModel : ObservableObject
break;
case NewlineSeparatorType.CR:
- if(character == '\r')
+ if (character == '\r')
{
result = IntroduceNewlineAfterThisCharacterResult.IntroduceNewline;
}
@@ -226,7 +243,7 @@ public partial class CommunicationDataViewModel : ObservableObject
}
if (character == '\n')
{
- if(previousCharacters != null && previousCharacters.Last() == '\r')
+ if (previousCharacters != null && previousCharacters.Last() == '\r')
{
result = IntroduceNewlineAfterThisCharacterResult.IntroduceNewline;
}
@@ -240,85 +257,29 @@ public partial class CommunicationDataViewModel : ObservableObject
return result;
}
- private int receivedDataCharacterCount = 0;
- private List? listOfPreviouslyReceivedCharacters = null;
- private void CommunicationProtocol_ReceivedDataEvent(object? sender, ReceivedDataEventArgs e)
- {
- HandleNewCharacters(this.ReceivedData, ref this.receivedDataCharacterCount, ref this.listOfPreviouslyReceivedCharacters, this.currentReceiveNewlineSeparatorType, e.ReceivedCharacters);
- }
- private int sentDataCharacterCount = 0;
- private List? listOfPreviouslySentCharacters = null;
- private void CommunicationProtocol_SentDataEvent(object? sender, SentDataEventArgs e)
- {
- HandleNewCharacters(this.SentData, ref this.sentDataCharacterCount, ref this.listOfPreviouslySentCharacters, this.currentSentNewlineSeparatorType, e.SentCharacters);
- }
+ #endregion
- ///
- /// Function that handles a list of new characters that should end up in the collection .
- /// In case a new line is required, according to the given , it is automatically introduced.
- /// Following parameters need to be referenced and stored outside: and .
- ///
- /// collection to add the characters to
- /// current line count
- /// list of previous character, newest at the last position of the list, null if nothing is stored
- /// separator between seperate lines
- /// characters to add to the
- /// in case of any error
- private void HandleNewCharacters(ObservableCollection dataCollection,
- ref int collectionLineCounter,
- ref List? previousCharacters,
- NewlineSeparatorType newlineSeparatorType,
- IEnumerable characters)
- {
- // go through every character
- foreach (var newExtdChar in characters)
- {
- // add to collection with the current counter, invoking UI context if necssary
- var currentLineCounter = collectionLineCounter;
- ContextHelpers.InvokeIfNecessary(this.uiContext, (Action)delegate
- {
- dataCollection.Add(new DataViewModel(newExtdChar, currentLineCounter));
- });
-
- switch (ShouldIntroduceNewlineAfterThisCharacter(newExtdChar.Character, previousCharacters, newlineSeparatorType))
- {
- case IntroduceNewlineAfterThisCharacterResult.NoNewline:
- // a decision could be made, previousCharacters can be cleared
- if (previousCharacters != null) { previousCharacters = null; }
- // nothing to do
- break;
+ #region String Manipulation
- case IntroduceNewlineAfterThisCharacterResult.IntroduceNewline:
- // a decision could be made, previousCharacters can be cleared
- if (previousCharacters != null) { previousCharacters = null; }
- // increase line count and break
- collectionLineCounter++;
- break;
-
- case IntroduceNewlineAfterThisCharacterResult.RequiresMoreCharacters:
- // first time that more characters are required => create new list
- previousCharacters ??= new List();
- // add current character to list
- previousCharacters.Add(newExtdChar.Character);
- break;
+ // TODO Implement Line Handling
+ private static string InsertNewCharactersIntoString(string dataAsString, IEnumerable newRawData)
+ {
+ string newDataAsString = dataAsString;
- default:
- throw new Exception($"'{nameof(HandleNewCharacters)}()' failed because of error when checking if a newline should be introduced.");
- }
+ foreach (ExtendedChar character in newRawData)
+ {
+ newDataAsString += character.Character;
}
- }
-
- [RelayCommand]
- private void ClearReceivedData()
- {
- this.ReceivedData = new ObservableCollection();
+ return newDataAsString;
}
- [RelayCommand]
- private void ClearSentData()
+ private static string ReorderString(ObservableCollection collection, NewlineSeparatorType value)
{
- this.SentData = new ObservableCollection();
+ // Not yet implemented
+ return "Not implemented";
}
+
+ #endregion
}
diff --git a/MultiTerm.Core/ViewModel/ICommunicationDataViewModel.cs b/MultiTerm.Core/ViewModel/ICommunicationDataViewModel.cs
new file mode 100644
index 0000000..076a452
--- /dev/null
+++ b/MultiTerm.Core/ViewModel/ICommunicationDataViewModel.cs
@@ -0,0 +1,35 @@
+using MultiTerm.Core.Types;
+using System.Collections.ObjectModel;
+
+namespace MultiTerm.Core.ViewModel;
+
+public interface ICommunicationDataViewModel where T_Data : IDataViewModel
+{
+ ///
+ /// Collection of data in context of a communication protocol.
+ ///
+ ObservableCollection Data { get; }
+
+ ///
+ /// String representation of .
+ ///
+ string DataAsString { get; }
+
+ ///
+ /// Collection of selected items of the .
+ /// May be set externally.
+ ///
+ ObservableCollection Selected { get; set; }
+
+ ///
+ /// Currently selected NewlineSeparator to group the into lines.
+ ///
+ NewlineSeparatorType NewlineSeparator { get; set; }
+
+ ///
+ /// Method to insert raw data into the Collection.
+ /// Also updates the property.
+ ///
+ /// collection of new data to insert
+ void HandleNewData(IEnumerable data);
+}
\ No newline at end of file
diff --git a/MultiTerm.Core/ViewModel/IDataViewModel.cs b/MultiTerm.Core/ViewModel/IDataViewModel.cs
new file mode 100644
index 0000000..7ba1c8f
--- /dev/null
+++ b/MultiTerm.Core/ViewModel/IDataViewModel.cs
@@ -0,0 +1,30 @@
+namespace MultiTerm.Core.ViewModel;
+
+public interface IDataViewModel
+{
+ ///
+ /// Allows frontent to group items by line identifier.
+ /// Can be set, e.g. to reorder items.
+ ///
+ int LineIdentifier { get; set; }
+
+ ///
+ /// Time when this data was produced.
+ ///
+ TimeOnly Time { get; }
+
+ ///
+ /// Hosts a displayable string of the character (UTF-16 encoded).
+ ///
+ string DisplayString { get; }
+
+ ///
+ /// Hosts a string of the character (hexadecimal format).
+ ///
+ string DisplayStringHex { get; }
+
+ ///
+ /// Hosts a string of the character (binary format).
+ ///
+ string DisplayStringBin { get; }
+}
diff --git a/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs b/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs
index 736bc8d..f29dc16 100644
--- a/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs
+++ b/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs
@@ -17,13 +17,13 @@ public partial class SendReceiveViewModel : TerminalViewModel
/// Send data model.
///
[ObservableProperty]
- private MultiFormatString sendData = new();
+ private MultiFormatString sendableData = new();
///
/// Temporary sent data property, for testing purposes.
///
[ObservableProperty]
- private string sentData = string.Empty;
+ private string tempSentDataString = string.Empty;
///
/// Constructor.
@@ -38,13 +38,13 @@ public partial class SendReceiveViewModel : TerminalViewModel
private void Send()
{
// Temp
- var items = this.CommunicationData.SelectedReceivedData;
- Debugger.Break();
- this.SentData = this.SendData.ToString();
+ //var items = this.CommunicationData.SelectedReceivedData;
+ //Debugger.Break();
+ this.TempSentDataString = this.SendableData.ToString();
// send data
- this.SendToCommunicationProtocol(this.SendData.ToString());
+ this.SendToCommunicationProtocol(this.SendableData.ToString());
// clear textbox
- this.SendData = new MultiFormatString();
+ this.SendableData = new MultiFormatString();
}
}
diff --git a/MultiTerm.Core/ViewModel/TerminalViewModel.cs b/MultiTerm.Core/ViewModel/TerminalViewModel.cs
index 8975fbf..0942c45 100644
--- a/MultiTerm.Core/ViewModel/TerminalViewModel.cs
+++ b/MultiTerm.Core/ViewModel/TerminalViewModel.cs
@@ -7,6 +7,7 @@ using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using MultiTerm.Core.Types;
using MultiTerm.Protocols;
+using MultiTerm.Protocols.Model;
using MultiTerm.Protocols.Types;
using System.Text;
@@ -58,66 +59,97 @@ public abstract partial class TerminalViewModel : ObservableObject, ITerminalVie
#endregion
///
- /// Holds communication data, meaning data that was sent to or received over the communication protocol.
+ /// Holds communication data that was received via the communication protocol.
///
[ObservableProperty]
- private CommunicationDataViewModel? communicationData;
+ private ICommunicationDataViewModel receivedData;
///
- /// Newline Separator Type that is selected for receival data of this Terminal. Defaults to none.
+ /// Holds communication data that was sent via the communication protocol.
///
[ObservableProperty]
- private NewlineSeparatorType receiveNewlineSeparatorType = NewlineSeparatorType.None;
+ private ICommunicationDataViewModel sentData;
///
- /// Newline Separator Type that is selected for sent out data of this Terminal. Defaults to none.
+ /// Defines at which newline sequence the displayed data is wrapped. Defaults to none.
+ ///
+ [ObservableProperty]
+ private NewlineSeparatorType dataDisplayNewlineSeparatorType = NewlineSeparatorType.None;
+
+ ///
+ /// Defines which Newline sequence is attached to data when it is sent. Defaults to none.
///
[ObservableProperty]
private NewlineSeparatorType sendNewlineSeparatorType = NewlineSeparatorType.None;
+ [ObservableProperty]
private ICommunicationProtocol? communicationProtocol;
- public ICommunicationProtocol? CommunicationProtocol
- {
- get { return this.communicationProtocol; }
- set
- {
- // store communication protocol
- this.communicationProtocol = value;
- // register communication protocol in the Communication Data View Model
- this.CommunicationData = new CommunicationDataViewModel(this.communicationProtocol, this.context);
+ [ObservableProperty]
+ private IProtocolSettingsViewModel? protocolSettings;
- // initializes default newline separators, requires communicationData to be not null
- this.InitializeNewlineSeparatorsFromAppSettings();
- // initialize both newline Separators. initializes with null if they are not available.
- this.CommunicationData.ConfigureNewlineSeparators(this.ReceiveNewlineSeparatorType, this.SendNewlineSeparatorType);
+ public TerminalViewModel(IAppSettingsProvider appSettings, IMessenger messenger, IContext context)
+ {
+ this.appSettings = appSettings;
+ this.messenger = messenger;
+ this.context = context;
+
+ // create new Communication data containers
+ this.receivedData = new CommunicationDataViewModel(this.context);
+ this.sentData = new CommunicationDataViewModel(this.context);
+ }
+
+ ~TerminalViewModel()
+ {
+ if (this.CommunicationProtocol != null)
+ {
+ this.CommunicationProtocol.ReceivedDataEvent -= CommunicationProtocol_ReceivedDataEvent;
+ this.CommunicationProtocol.SentDataEvent -= CommunicationProtocol_SentDataEvent;
+ this.CommunicationProtocol = null;
}
}
- private IProtocolSettingsViewModel? protocolSettings;
- public IProtocolSettingsViewModel? ProtocolSettings
+ #region Communication Protocol
+ partial void OnCommunicationProtocolChanged(ICommunicationProtocol? value)
{
- get { return this.protocolSettings; }
- set
+ this.InitializeCommunicationProtocol();
+ }
+
+ private void InitializeCommunicationProtocol()
+ {
+ if (this.CommunicationProtocol != null)
{
- this.protocolSettings = value;
- // register event handler for connection request from viewmodel
- if(value != null)
- {
- this.protocolSettings!.ConnectRequested += OnViewModelRequestedConnect;
- this.protocolSettings!.DisconnectRequested += OnViewModelRequestedDisconnect;
- }
+ this.CommunicationProtocol.ReceivedDataEvent += CommunicationProtocol_ReceivedDataEvent;
+ this.CommunicationProtocol.SentDataEvent += CommunicationProtocol_SentDataEvent;
}
+
+ // initializes default newline separators, updates them directly inside ReceivedData and SentData objects
+ this.InitializeNewlineSeparatorsFromAppSettings();
+
+ // update newline settings in data objects
+ this.ReceivedData.NewlineSeparator = this.DataDisplayNewlineSeparatorType;
+ this.SentData.NewlineSeparator = this.DataDisplayNewlineSeparatorType;
}
- public TerminalViewModel(IAppSettingsProvider appSettings, IMessenger messenger, IContext context)
+ private void CommunicationProtocol_ReceivedDataEvent(object? sender, ReceivedDataEventArgs e)
{
- this.appSettings = appSettings;
- this.messenger = messenger;
- this.context = context;
+ // guard null
+ if (this.ReceivedData == null) { throw new NullReferenceException($"{nameof(CommunicationProtocol_ReceivedDataEvent)} found {nameof(this.ReceivedData)} to be null."); }
+ // handover data
+ this.ReceivedData.HandleNewData(e.ReceivedCharacters);
+ }
+
+ private void CommunicationProtocol_SentDataEvent(object? sender, SentDataEventArgs e)
+ {
+ // guard null
+ if (this.SentData == null) { throw new NullReferenceException($"{nameof(CommunicationProtocol_SentDataEvent)} found {nameof(this.SentData)} to be null."); }
+ // handover data
+ this.SentData.HandleNewData(e.SentCharacters);
}
+ #endregion
+
///
/// Sends the given string to this instances , UTF-16 encoded.
/// Appends configured to the end of string.
@@ -125,7 +157,7 @@ public abstract partial class TerminalViewModel : ObservableObject, ITerminalVie
/// data string
protected void SendToCommunicationProtocol(string data)
{
- // guard communication protocol null
+ // guard null values
if(this.CommunicationProtocol == null) { throw new NullReferenceException($"'{nameof(SendToCommunicationProtocol)}()' was called but {nameof(CommunicationProtocol)} is null."); }
// inform user and quit if communication protocol is not connected
@@ -154,6 +186,18 @@ public abstract partial class TerminalViewModel : ObservableObject, ITerminalVie
this.CommunicationProtocol.SendBytes(byteArray);
}
+ #region Protocol Settings
+ partial void OnProtocolSettingsChanged(IProtocolSettingsViewModel? value)
+ {
+ // register event handler for connection request from viewmodel
+ if (value != null)
+ {
+ this.ProtocolSettings!.ConnectRequested += OnViewModelRequestedConnect;
+ this.ProtocolSettings!.DisconnectRequested += OnViewModelRequestedDisconnect;
+ }
+ }
+ #endregion
+
#region Connect/Disconnect
private void OnViewModelRequestedConnect(object? sender, ConnectionRequestEventArgs e)
{
@@ -196,22 +240,20 @@ public abstract partial class TerminalViewModel : ObservableObject, ITerminalVie
#region Newline Separator handling
///
/// Gets the default settings for both newline separators from the AppSettings Provider.
- /// Writes them to the local variables and .
+ /// Writes them to the local variables and .
/// In case there are no default settings, it does not overwrite the local variables.
- /// In case the Communication Data is null, nothing is done.
///
private void InitializeNewlineSeparatorsFromAppSettings()
{
- // guard null objects
- if(this.CommunicationData == null) { return; }
-
- // get newline separators from persistent settings, if not available catch exceptions
+ // get newline separators from persistent settings, if not available catch exceptions. apply to displayed data variable.
this.appSettings.TryReadSetting(defaultReceiveNewlineSeparatorAppSettingsKey, out string settingValueReceiveNLSep);
try
{
- this.ReceiveNewlineSeparatorType = EnumHelpers.ParseEnum(settingValueReceiveNLSep);
+ this.DataDisplayNewlineSeparatorType = EnumHelpers.ParseEnum(settingValueReceiveNLSep);
}
catch { }
+
+ // apply to send newline separator
this.appSettings.TryReadSetting(defaultSendNewlineSeparatorAppSettingsKey, out string settingValueSendNLSep);
try
{
@@ -220,16 +262,17 @@ public abstract partial class TerminalViewModel : ObservableObject, ITerminalVie
catch { }
}
- partial void OnReceiveNewlineSeparatorTypeChanged(NewlineSeparatorType value)
- {
- // triggers rearranging the received data with the new NewlineSeparatorType
- this.CommunicationData?.ConfigureNewlineSeparators(value, null);
- }
-
- partial void OnSendNewlineSeparatorTypeChanged(NewlineSeparatorType value)
- {
- // triggers rearranging the sent data with the new NewlineSeparatorType
- this.CommunicationData?.ConfigureNewlineSeparators(null, value);
+ partial void OnDataDisplayNewlineSeparatorTypeChanged(NewlineSeparatorType value)
+ {
+ // triggers rearranging the displayed data with the new NewlineSeparatorType
+ if (this.ReceivedData != null)
+ {
+ this.ReceivedData.NewlineSeparator = value;
+ }
+ if (this.SentData != null)
+ {
+ this.SentData.NewlineSeparator = value;
+ }
}
#endregion
diff --git a/MultiTerm.Wpf.CustomControl/MultiFormatDataView/MultiFormatDataView.cs b/MultiTerm.Wpf.CustomControl/MultiFormatDataView/MultiFormatDataView.cs
index c4c772a..031ac40 100644
--- a/MultiTerm.Wpf.CustomControl/MultiFormatDataView/MultiFormatDataView.cs
+++ b/MultiTerm.Wpf.CustomControl/MultiFormatDataView/MultiFormatDataView.cs
@@ -7,35 +7,29 @@ using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Linq;
-using MultiTerm.Wpf.CustomControl.ValueConverter;
-using System.Diagnostics.Metrics;
+using System.Collections.Specialized;
+using MultiTerm.Protocols.Model;
+using System.Collections.ObjectModel;
namespace MultiTerm.Wpf.CustomControl;
public class MultiFormatDataView : Control
{
private static readonly Dictionary itemParentPairs = new();
- private const string itemsControlTemplateName = "itemsControl";
+ private const string itemsControlTemplateName = "PART_ItemsControl";
private const string buttonClearTemplateName = "btnClear";
private const string selectorTemplateName = "comboBoxSelector";
- private const string textBoxCharOnlyViewTemplateName = "textBoxCharactersOnlyView";
+ private const string textBoxCharOnlyViewTemplateName = "PART_CharOnlyTextBox";
private ListBox? itemsControl;
private TextBox? tbCharOnlyView;
+ private ICollectionView? collectionView;
#region Dependency Properties
public static readonly DependencyProperty DataSourceProperty =
DependencyProperty.Register("DataSource",
- typeof(IEnumerable), typeof(MultiFormatDataView),
+ typeof(ICommunicationDataViewModel), typeof(MultiFormatDataView),
new PropertyMetadata(null, OnDataSourcePropertyChanged));
- public static readonly DependencyProperty SelectedItemsProperty =
- DependencyProperty.Register("SelectedItems",
- typeof(IList), typeof(MultiFormatDataView),
- new FrameworkPropertyMetadata(OnSelectedItemsPropertyChanged)
- {
- BindsTwoWayByDefault = false
- });
-
public static readonly DependencyProperty SelectorItemsSourceProperty =
DependencyProperty.Register("SelectorItemsSource",
typeof(IEnumerable), typeof(MultiFormatDataView),
@@ -70,24 +64,15 @@ public class MultiFormatDataView : Control
public static readonly RoutedEvent ClearRequestedEvent;
- ///
- /// .NET Property for DataSource.
- ///
- [Bindable(true)]
- public IEnumerable DataSource
- {
- get { return (IEnumerable)GetValue(DataSourceProperty); }
- set { SetValue(DataSourceProperty, value); }
- }
///
- /// .NET Property for SelectedItems.
+ /// .NET Property for DataSourceProperty.
///
[Bindable(true)]
- public IList SelectedItems
+ public ICommunicationDataViewModel DataSource
{
- get { return (IList)GetValue(SelectedItemsProperty); }
- set { SetValue(SelectedItemsProperty, value); }
+ get { return (ICommunicationDataViewModel)GetValue(DataSourceProperty); }
+ set { SetValue(DataSourceProperty, value); }
}
///
@@ -170,7 +155,7 @@ public class MultiFormatDataView : Control
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
- this.SelectedItems = new List();
+ this.Unloaded += MultiFormatDataView_Unloaded;
// get itemsControl from template
if (GetTemplateChild(itemsControlTemplateName) is ListBox listBox)
@@ -183,17 +168,22 @@ public class MultiFormatDataView : Control
throw new Exception($"Implementation fault, {itemsControlTemplateName} not found in template.");
}
- // get button from template, ignore if it does not exist
- if (GetTemplateChild(buttonClearTemplateName) is Button button)
- {
- button.Click += OnClearButtonClicked; ;
- }
-
- // get textBox from template, ignore if it does not exist
+ // get textBox from template
if (GetTemplateChild(textBoxCharOnlyViewTemplateName) is TextBox tb)
{
this.tbCharOnlyView = tb;
this.tbCharOnlyView.SelectionChanged += TextBoxCharOnlyView_SelectionChanged;
+ this.tbCharOnlyView.TextChanged += TextBoxCharOnlyView_TextChanged;
+ }
+ else
+ {
+ throw new Exception($"Implementation fault, {textBoxCharOnlyViewTemplateName} not found in template.");
+ }
+
+ // get button from template, ignore if it does not exist
+ if (GetTemplateChild(buttonClearTemplateName) is Button button)
+ {
+ button.Click += OnClearButtonClicked; ;
}
}
@@ -202,58 +192,62 @@ public class MultiFormatDataView : Control
// extract instance and guard null
if (d is not MultiFormatDataView mfdv) { return; }
- // extract instance of new Value and check if correct type
- if (e.NewValue is not IEnumerable newDataSource)
+ // manually create collection view
+ ICollectionView cv = CollectionViewSource.GetDefaultView(mfdv.DataSource.Data);
+ // add grouping
+ PropertyGroupDescription groupDescription = new(nameof(CharacterDataViewModel.LineIdentifier));
+ cv.GroupDescriptions.Add(groupDescription);
+ // add live grouping
+ if (cv is ICollectionViewLiveShaping cvLiveShaping && cvLiveShaping.CanChangeLiveGrouping)
{
- throw new ArgumentException($"{nameof(MultiFormatDataView)}: {nameof(DataSourceProperty)} must be of type {nameof(IEnumerable)}");
+ cvLiveShaping.LiveGroupingProperties.Add(nameof(CharacterDataViewModel.LineIdentifier));
+ cvLiveShaping.IsLiveGrouping = true;
}
+ // save collection view
+ mfdv.collectionView = cv;
+ // apply collection view as itemssource
+ mfdv.itemsControl!.ItemsSource = cv;
+
+ // register to collection changed event
+ if (mfdv.DataSource.Data is INotifyCollectionChanged incc)
+ {
+ incc.CollectionChanged += mfdv.Data_CollectionChanged;
+ }
+
+ // create binding for textbox (DataAsString)
+ var binding = new Binding()
+ {
+ RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent),
+ Path = new PropertyPath($"{nameof(mfdv.DataSource)}.{nameof(mfdv.DataSource.DataAsString)}")
+ };
+ BindingOperations.SetBinding(mfdv.tbCharOnlyView, TextBox.TextProperty, binding);
+ }
- // TODO REMOVE
- //// validate that no characters were removed
- //if(oldDataSource != null && oldDataSource.Count() > newDataSource.Count())
- //{
- // throw new NotImplementedException($"{nameof(MultiFormatDataView)} cannot handle removing single items from DataSource. " +
- // $"Only adding and clearing ({nameof(DataSourceProperty)} = null) are supported.");
- //}
- //// iterate through data, adding content to textbox
- //int prevCounter = newDataSource.First().LineIdentifier;
- //for(int i = 0; i < newDataSource.Count(); i++)
+ private void Data_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
+ {
+ // TEMP scroll to added item if not null
+ //if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems != null && e.NewItems[0] != null)
//{
- // DataViewModel item = newDataSource.ElementAt(i);
- // DataViewModel? oldItem = oldDataSource?.ElementAtOrDefault(i);
-
- // // if old item at this position exists and it equals the new item => skip
- // if(oldItem != null && oldItem.Equals(item))
- // {
- // continue;
- // }
-
- // // new item found: add it as content to textbox
- // if (mfdv.tbCharOnlyView != null)
- // {
- // // newline if previous counter is lower than this
- // if (item.LineIdentifier > prevCounter)
- // {
- // mfdv.tbCharOnlyView.Text += "\n";
- // prevCounter = item.LineIdentifier;
- // }
- // // add character (text)
- // mfdv.tbCharOnlyView.Text += item.DisplayStringUtf16;
- // }
+ // this.itemsControl!.ScrollIntoView(e.NewItems[0]);
//}
+ }
- // add group property to support grouping of VirtualizingWrapPanel
- CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(e.NewValue);
- PropertyGroupDescription groupDescription = new(nameof(DataViewModel.LineIdentifier));
- view.GroupDescriptions.Add(groupDescription);
+ ///
+ /// On Unload remove event handler.
+ ///
+ private void MultiFormatDataView_Unloaded(object sender, RoutedEventArgs e)
+ {
+ if (DataSource is INotifyCollectionChanged incc)
+ {
+ incc.CollectionChanged -= Data_CollectionChanged;
+ }
}
private void OnClearButtonClicked(object sender, RoutedEventArgs e)
{
// raise clear requested event
- RoutedEventArgs args = new(ClearRequestedEvent);
- RaiseEvent(args);
+ this.DataSource.Data.Clear();
}
#region Selected Items handling
@@ -266,26 +260,25 @@ public class MultiFormatDataView : Control
if (this.tbCharOnlyView != null && this.tbCharOnlyView.SelectionLength > 0) { this.tbCharOnlyView.Select(0, 0); }
// otherwise update internal list
- foreach (DataViewModel item in e.RemovedItems)
+ foreach (CharacterDataViewModel item in e.RemovedItems)
{
- this.SelectedItems.Remove(item);
+ this.DataSource.Selected.Remove(item);
}
- foreach (DataViewModel item in e.AddedItems)
+ foreach (CharacterDataViewModel item in e.AddedItems)
{
- this.SelectedItems.Add(item);
+ this.DataSource.Selected.Add(item);
}
}
private void TextBoxCharOnlyView_SelectionChanged(object sender, RoutedEventArgs e)
{
- var newSelection = new List();
+ var newSelection = new ObservableCollection();
int selectionStartIndex = this.tbCharOnlyView!.SelectionStart;
+ // TEMP OLD
// extract text from the beginning to the start of the selected text
- var textFromBeginningToStartOfSelection = this.tbCharOnlyView!.Text.Substring(0, selectionStartIndex);
+ // var textFromBeginningToStartOfSelection = this.tbCharOnlyView!.Text.Substring(0, selectionStartIndex);
// count amount of manually introduced newline sequences in this text section (these to not exist in the data source!)
- var foundManuallyIntroducedNewlineSequences = textFromBeginningToStartOfSelection.Count((x) => x == DataViewModelToStringConverter.NewlineSequence);
- // convert datasource
- var collection = ((IEnumerable)this.DataSource);
+ var foundManuallyIntroducedNewlineSequences = 0; // = textFromBeginningToStartOfSelection.Count((x) => x == DataViewModelToStringConverter.NewlineSequence);
// iterate through length of selection
for (int i = 0; i < this.tbCharOnlyView!.SelectionLength; i++)
@@ -293,21 +286,21 @@ public class MultiFormatDataView : Control
// subtracting the counted newline sequences and adding i (length)
int elementPositionInCollection = selectionStartIndex - foundManuallyIntroducedNewlineSequences + i;
// add element to new selection list
- newSelection.Add(collection.ElementAt(elementPositionInCollection));
+ newSelection.Add(this.DataSource.Data.ElementAt(elementPositionInCollection));
// next item does not exist => break loop
- if(collection.ElementAtOrDefault(elementPositionInCollection + 1) == null)
+ if(this.DataSource.Data.ElementAtOrDefault(elementPositionInCollection + 1) == null)
{
break;
}
}
// update property
- this.SelectedItems = newSelection;
+ this.DataSource.Selected = newSelection;
}
- private static void OnSelectedItemsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ private void TextBoxCharOnlyView_TextChanged(object sender, TextChangedEventArgs e)
{
- // NOP
+ this.tbCharOnlyView?.ScrollToEnd();
}
#endregion
diff --git a/MultiTerm.Wpf.CustomControl/MultiFormatDataView/MultiFormatDataView.xaml b/MultiTerm.Wpf.CustomControl/MultiFormatDataView/MultiFormatDataView.xaml
index c0b3a63..019f419 100644
--- a/MultiTerm.Wpf.CustomControl/MultiFormatDataView/MultiFormatDataView.xaml
+++ b/MultiTerm.Wpf.CustomControl/MultiFormatDataView/MultiFormatDataView.xaml
@@ -3,7 +3,6 @@
xmlns:local="clr-namespace:MultiTerm.Wpf.CustomControl"
xmlns:vm="clr-namespace:MultiTerm.Core.ViewModel;assembly=MultiTerm.Core"
xmlns:wpftk="clr-namespace:WpfToolkit.Controls;assembly=VirtualizingWrapPanel"
- xmlns:conv="clr-namespace:MultiTerm.Wpf.CustomControl.ValueConverter"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
-
-
-