Vielen dank für die Hinweise.
Dann werde ich das Ticket beobachten und wenn es kommt den Code anpassen.
Und das mit dem "stackalloc" ist auch sehr interessant. Auch dafür vielen Dank.
Ich denke ich habe nun die Lösung gefunden, nachdem ich in den Sourcecode angeschaut habe.
Man muss z.B.
Span<Range> ranges = new Range[] { Range.All, Range.All };
verwenden. Dann befüllt er auch beide.
Hallo zusammen,
ich wollte gerade auf einem ReadOnlySpan<char> Split aufrufen. Jedoch bekommen ich immer für count 0 zurück
ReadOnlySpan<char> toSplit = "Hallo Welt";
Span<Range> ranges = new Span<Range>();
var count = toSplit.Split(ranges, ' ');
Leider sehe ich nicht was ich falsch mache. Bei IndexOf gibt er mir für ' ' die richtige Position.
Schöne Grüße und vielen Dank
Permutation
Den Artikel hab ich auf https://stackoverflow.com/a/2583969 auch gefunden. Im ersten Kommentar ist eigentlich auch mein Problem beschrieben. Aber eben leider keine Lösung gesehen. Bzw. gehofft, dass sich in der Zwischenzeit evtl. was geändert hat.
EDIT:
Aber den zweiten Artikel kannte ich noch nicht. Schade, dann ist das eventuell wirklich nicht möglich.
Da ich jedoch die XSD parse kann ich auf solche Dinge reagieren und muss dann "Zwischenobjekte" anlegen analog wie in dem Artikel. Ich hatte gehofft dies vermeiden zu können um Zeit und Speicher zu sparen...
Aber vielen vielen Dank für Deine Zeit und Hinweise.
Ja genau ich brauch die Reihenfolge, da ich bei der Verarbeitung ja wissen muss was z.B. in <A>...</A> stand.
Ein RoundTrip ist so auch nicht möglich, da er beim Serialisieren dann einen Fehler wirft. Lasse ich es wie es ursprünglich war (mit dem Text Property), dann kommt folgendes raus:
<?xml version="1.0" encoding="utf-8"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<A>a</A>
<B>b</B>
<C>c</C>
<A>aa</A>
<B>bb</B>
<C>cc</C>abc</Root>
D.h. beide "Lösungen" bringen mich leider nicht weiter, da "Wissen" verloren geht.
Und gibst du das Schema beim Deserialisieren mit (denn dort ist ja
Text
nicht definiert)?
Nein das gebe ich nicht mit an. Das Text
und Items
Property sind beide nicht im Schema, werden aber über die Attribute richtig "gesteuert".
Dann kommt liest er den "mixed" Inhalt nicht mehr und kommt z.B. in das Event
private static void XmlSerializer_UnknownNode(object? sender, XmlNodeEventArgs e)
{
throw new NotImplementedException();
}
mit
Name | Wert | Typ | |
---|---|---|---|
◢ | e | {System.Xml.Serialization.XmlNodeEventArgs} | System.Xml.Serialization.XmlNodeEventArgs |
LineNumber | 2 | int | |
LinePosition | 9 | int | |
LocalName | "#text" | string | |
Name | "#text" | string | |
NamespaceURI | "" | string | |
NodeType | Text | System.Xml.XmlNodeType | |
▶ ObjectBeingDeserialized | {XSDTest.Misc.Choice} | object {XSDTest.Misc.Choice} | |
Text | "a" | string |
EDIT:
mit "#text" hab ich es auch schon probiert.
Hallo zusammen,
ich habe eine Frage zum Serialisieren. Dazu ein kleines Beispiel:
Dies ist das Schema für eine XML Datei die gelesen werden soll:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xsd:complexType abstract="false" mixed="true" name="Choice">
<xsd:choice maxOccurs="unbounded" minOccurs="0">
<xsd:element name="A" type="xsd:string"/>
<xsd:element name="B" type="xsd:string"/>
<xsd:element name="C" type="xsd:string"/>
</xsd:choice>
</xsd:complexType>
<xsd:element name="Root" type="Choice"/>
</xsd:schema>
Und hier die XML dazu:
<?xml version="1.0" encoding="utf-8"?>
<Root>a<A>a</A>b<B>b</B>c<C>c</C><A>aa</A><B>bb</B><C>cc</C></Root>
Wenn ich nun z.B. mit dem Tool xsd.exe mir Code erzeuge bekomme ich folgendes:
using System.Xml.Serialization;
namespace XSDTest.Misc {
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")]
[Serializable()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[XmlRoot("Root", Namespace="", IsNullable=false)]
public partial class Choice {
/// <remarks/>
[XmlText(typeof(string))]
[XmlElement("A", typeof(string))]
[XmlElement("B", typeof(string))]
[XmlElement("C", typeof(string))]
[XmlChoiceIdentifier("ItemsElementName")]
public string[] Items;
/// <remarks/>
[XmlElement("ItemsElementName")]
[XmlIgnore()]
public ItemsChoiceType[] ItemsElementName;
///// <remarks/>
//[System.Xml.Serialization.XmlTextAttribute()]
//public string[] Text;
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")]
[Serializable()]
[XmlType(IncludeInSchema=false)]
public enum ItemsChoiceType {
/// <remarks/>
A,
/// <remarks/>
B,
/// <remarks/>
C,
}
}
Ich habe nachträglich das Text Property entfernt und XmlText(typeof(string))]
bei Items hinzugefügt, damit ich es "richtig" lesen kann. Nun habe ich aber das Problem, dass ich folgendes Resultat bekomme:
Name | Wert | Typ | |
---|---|---|---|
◢ | Items | {string[9]} | string[] |
[0] | "a" | string | |
[1] | "a" | string | |
[2] | "b" | string | |
[3] | "b" | string | |
[4] | "c" | string | |
[5] | "c" | string | |
[6] | "aa" | string | |
[7] | "bb" | string | |
[8] | "cc" | string | |
◢ | ItemsElementName | {XSDTest.Misc.ItemsChoiceType[6]} | XSDTest.Misc.ItemsChoiceType[] |
[0] | A | XSDTest.Misc.ItemsChoiceType | |
[1] | B | XSDTest.Misc.ItemsChoiceType | |
[2] | C | XSDTest.Misc.ItemsChoiceType | |
[3] | A | XSDTest.Misc.ItemsChoiceType | |
[4] | B | XSDTest.Misc.ItemsChoiceType | |
[5] | C | XSDTest.Misc.ItemsChoiceType |
Mit diesem Ergebnis kann ich leider nicht viel Anfangen, ich hab schon probiert, den Enum zu erweitern, damit ich bei ItemsElementName die selbe Anzahl bekomme wie bei Items.
z.B.
[XmlType(IncludeInSchema=false)]
public enum ItemsChoiceType {
// -------------
None,
[System.Xml.Serialization.XmlEnum("#text")]
Text,
// ------------
/// <remarks/>
A,
/// <remarks/>
B,
/// <remarks/>
C,
}
Leider hat bisher nichts funktioniert. Daher meine Frage, wie kann ich den Enum ItemsChoiceType
so erweitern, dass ItemsElementName auch 9 Einträge hat, oder muss ich es ganz anders machen?
Viele Grüße und vielen Dank
Quaneu
Update:
Ich konnte die Fehler jetzt "lösen", bzw. kommen sie nicht mehr. Aber leider zeigt mir der AssemblyResolver trotzdem noch .Net Framework an 😦
Auf github habe ich die Lösung gefunden. Also wenn ich auf dem "refs" Ordner nur noch die ""netstandard.dll" kommen keine Fehler mehr. Bleibt noch das ".Net Framework" Problem...
Einen ähnlichen Artikel habe ich auch schon gefunden, aber diese Lösung bezieht sich wohl nur auf "Console Application" und nicht auf "Class Library". Aber ich kann es mal probieren.
Edit1:
Also habe jetzt mal die Datei neben die generierte dll geleget, aber leider bringt das auch nichts.
Edit2:
Bild aus ILSpy.
Hier mein Code:
private static CSharpCompilation CreateCompileUnit(string dllName, NamespaceDeclarationSyntax namespaceDeclaration)
{
CompilationUnitSyntax compileUnit = SyntaxHelper.BuildCompilationUnit(namespaceDeclaration);
string sourceCodeAsText = compileUnit.NormalizeWhitespace("\t", Environment.NewLine).ToFullString();
SyntaxTree tree = CSharpSyntaxTree.ParseText(sourceCodeAsText);
SyntaxTree[] trees = { tree };
CSharpCompilationOptions compilerOptions = new CSharpCompilationOptions(
OutputKind.DynamicallyLinkedLibrary, optimizationLevel: OptimizationLevel.Debug, platform: Platform.X64);
var coreDir = Path.GetDirectoryName(typeof(object).GetTypeInfo().Assembly.Location);
MetadataReference[] reference =
{
MetadataReference.CreateFromFile(Path.Combine(coreDir, "System.Private.CoreLib.dll")),
MetadataReference.CreateFromFile(Path.Combine(coreDir, "System.Private.Xml.dll")),
MetadataReference.CreateFromFile(Path.Combine(coreDir, "System.Private.Uri.dll")),
MetadataReference.CreateFromFile(Path.Combine(coreDir, "System.Runtime.dll")),
MetadataReference.CreateFromFile(Path.Combine(coreDir, "System.Runtime.Extensions.dll")),
MetadataReference.CreateFromFile(Path.Combine(coreDir, "System.Xml.ReaderWriter.dll")),
MetadataReference.CreateFromFile(Path.Combine(coreDir, "System.Text.RegularExpressions.dll"))
};
CSharpCompilation compilation = CSharpCompilation.Create(dllName, trees, reference, compilerOptions);
return compilation;
}
Ich habe es bisher mit Emit(Stream) aufgerufen. Auch wenn ich es mit den Deinem Vorschlag probiere klappt es leider nicht.
Wenn ich selbst eine .Net Core dll erstelle und in einem anderen Projekt einbinde, muss ich auch nicht die "System.Private.CoreLib" dlls usw. einbinden.
Ich hatte in meinem ersten Beitrag auch erwähnt, dass der Assembly Explorer für die generierte dll .Net Framework anzeigt, was mirfalsch vorkommt. Wenn ich eine .Net Core dll anschaue bekomme ich das nicht. Ich habe mal ein Bild angefügt, damit man sehen kann, was ich meine. Aber ich weiß nicht warum er keine .Net Core dll generiert...
Update:
Selbst wenn ich die generierte dll in ein .Net Standard Projekt einbinde, bekomme ich die Fehler. Ich denke beim bauen der dll geht etwas schief. bzw. mache ich ein Fehler. Aber leider sehe ich den Fehler nicht...
Was meinst Du mit so geschrieben?
Also es darf auch gern .NET Standard sein. Aber beim erstellen der dll, kann ich dies nicht angeben, bzw. habe ich bisher nichts gefunden.
Aber wie geschrieben klappt dies nicht. Die generierte dll lässt sich einbinden, aber ich bekomme immer die Fehler aus meinem ersten Post.
Edit:
Noch mal als Information:
Ich habe ein .Net Core 3.1 Projekt, dass Code generieren soll, bzw. eine dll. Die dll die generiert wurde, binde ich in einen Testprojekt ein, das auch ein .Net Core 3.1 Projekt ist. Sobald ich Code aus der generierten dll verwenden will, zeigt mir VS die besagten Fehler an.
Hallo zusammen,
ich habe mit Roslyn eine dll in einem .Net Core 3.1 Projekt generiert. Dazu erstelle ich eine CSharpCompilation Instanz und rufe auf ihr Emit(...) auf. Dies klappt alles und das EmitResult hat keine Fehler.
Folgende Referenzen benutze ich in dieser dll.
var coreDir = Path.GetDirectoryName(typeof(object).GetTypeInfo().Assembly.Location);
MetadataReference[] reference =
{
MetadataReference.CreateFromFile(Path.Combine(coreDir, "System.Private.CoreLib.dll")),
MetadataReference.CreateFromFile(Path.Combine(coreDir, "System.Private.Xml.dll")),
MetadataReference.CreateFromFile(Path.Combine(coreDir, "System.Private.Uri.dll")),
MetadataReference.CreateFromFile(Path.Combine(coreDir, "System.Runtime.dll")),
MetadataReference.CreateFromFile(Path.Combine(coreDir, "System.Runtime.Extensions.dll")),
MetadataReference.CreateFromFile(Path.Combine(coreDir, "System.Xml.ReaderWriter.dll")),
MetadataReference.CreateFromFile(Path.Combine(coreDir, "System.Text.RegularExpressions.dll"))
};
Wenn ich nun die erstellte dll in meinem Test (auch eine .Net Core 3.1 Projekt) einbinde, bekomme ich folgende Fehler, für Code aus dieser dll.
Fehlermeldung:
Error CS0012 The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
Error CS0012 The type 'Stream' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
Ich verstehe nicht was ich falsch mache. Mein Ziel ist es, das die dll auch ein .Net Core oder .Net Standard Projekt ist. Leider habe ich dazu keine Einstellungen gefunden, bzw. gelesen das der Output anscheinend imme ein .Net Standard Projekt sein soll. Wenn ich jedoch im Assembly Explorer die dll anschaue steht dabei, "... (x64, .Net Framework v4.7.2, Debug).
Ich hoffe mir kann wer einen Hinweis geben, was ich falsch mache bzw. vergessen habe.
Schöne Grüße
Quaneu
Und müßte xml:space="preserve" nicht innerhalb der XML-Datei stehen?
Du hast vollkommen recht... sorry. Damit bekomme ich dann auch IgnoreWhitespace = true einen SignificantWhitespace Node. Jetzt passt auch wieder alles.
Du erhältst also Whitespace innerhalb des Text-Node?
Ja die bekomme ich.
WhitesapceHandling steht bei dir aber auf All (default)?
Also ich setzte nichts. Ich benutze ja XmlReader.Create mit den Settings.
Vielen vielen Dank für deine Hilfe 👍
In der Doku zu Ignorewhitespace steht folgendes
Leerraum, der nicht als signifikant betrachtet wird, umfasst Leerzeichen, Tabstopps und leere Zeilen, mit denen das Markup für eine bessere Lesbarkeit festgelegt wird. Ein Beispiel hierfür ist Leerraum im Element Inhalt.
Diese Eigenschafts Einstellung wirkt sich nicht auf Leerraum zwischen Markup in einem gemischten Inhalts Modus oder Leerraum aus, der innerhalb des Gültigkeits Bereichs eines xml:space='preserve' Attributs auftritt.
Daher dachte ich ich kann es auf true lassen.
Selbst wenn ich im Schema folgendes schreibe
<xs:element name="Property_9" type="ComplexType_2" xml:space="preserve"/>
Bekomme ich nur bei Ignorewhitespace = false einen Whitespace Node.
Dies widerspricht sich doch mit der Dokumentation, oder?
Edit: Zu deiner Frage:
Also ich bekomme folgendes:
"
text text2
text3 "
als Text und der Rest verhält sich wie bei meinem Beispiel.
Hallo zusammen,
ich versuche gerade eine XML Datei mit dem XmlReader einzulesen. Dabei bin ich über folgendes Problem gestolpert.
Den XmlReader lege ich wie folgt an
XmlReaderSettings xmlReaderSettings = new XmlReaderSettings{IgnoreComments = true, IgnoreProcessingInstructions = true, IgnoreWhitespace = true};
xmlReaderSettings.ValidationType = ValidationType.Schema;
xmlReaderSettings.ValidationEventHandler += validationEventHandler;
using (XmlReader xmlReader = XmlReader.Create(stream, xmlReaderSettings))
{
return Reader.ReadContent(xmlReader);
}
Das Element das Probleme verursacht sieht im Schema wie folgt aus
<xs:complexType name="ComplexType_2" mixed="true">
<xs:sequence>
<xs:element name="ComplexType_2_Property_1" type="xs:string"/>
</xs:sequence>
</xs:complexType>
Und in der XML wie folgt
<Property_9>
text<ComplexType_2_Property_1>ComplexType_2_Property_11</ComplexType_2_Property_1>
</Property_9>
Wenn ich nun mit dem Reader dieses Element lesen will bekomme ich nie den Zeilenumbruch und "\t" nach </ComplexType_2_Property_1> obwohl es ja mixed ist. Wenn ich IgnoreWhitespace auf false setze bekomme ich es zwar als Whitespace Node aber nicht als SignificantWhitespace Node. Leider verstehe ich nicht, was ich falsch mache bzw. wo mein Denkfehler liegt.
Der Code zum Lesen sieht wie folgt aus (ist generiert):
public static ComplexType_2_T Read_ComplexType_2_T(XmlReader xmlReader)
{
var instance = new ComplexType_2_T();
int position = -1;
while (xmlReader.Read())
{
SkipRead:
switch (xmlReader.NodeType)
{
case XmlNodeType.Element:
switch (xmlReader.Name)
{
case "ComplexType_2_Property_1":
if (position == 0)
return instance;
instance.Add_ComplexType_2_Property_1_P(xmlReader.ReadElementString());
position = 0;
goto SkipRead;
default:
return instance;
}
case XmlNodeType.Text:
instance.Add_MixedContent(xmlReader.Value);
break;
case XmlNodeType.Whitespace:
break;
case XmlNodeType.SignificantWhitespace:
break;
}
}
return instance;
}
Vielen Dank schon mal für die Hinweise
Schöne Grüße
Quaneu
Ich habe jetzt eine Lösung gefunden 😃.
Ich habe nun eine Klasse die für das Gruppieren zuständig ist. Diese stellt ein Property Collection bereit, an die sich das Grid binden kann. Wenn man nun gruppieren will, erstelle ich eine neue ListCollectionView in einem Task und gruppiere in diesem. Danach wird diese dem Property Collection hinzugefügt. Klappt bisher ganz gut 😃
Hatte wolh ein Brett vorm Kopf, da ich Anfangs die Collection nur einmal (OneTime) binden wollte...
Schöne Grüße
Quanue
Hello Schleenz1984,
here is an example from RichTextBox
public BasicRichTextBoxWithContentExample()
{
StackPanel myStackPanel = new StackPanel();
// Create a FlowDocument to contain content for the RichTextBox.
FlowDocument myFlowDoc = new FlowDocument();
// Create a Run of plain text and some bold text.
Run myRun = new Run("This is flow content and you can ");
Bold myBold = new Bold(new Run("edit me!"));
// Create a paragraph and add the Run and Bold to it.
Paragraph myParagraph = new Paragraph();
myParagraph.Inlines.Add(myRun);
myParagraph.Inlines.Add(myBold);
// Add the paragraph to the FlowDocument.
myFlowDoc.Blocks.Add(myParagraph);
RichTextBox myRichTextBox = new RichTextBox();
// Add initial content to the RichTextBox.
myRichTextBox.Document = myFlowDoc;
myStackPanel.Children.Add(myRichTextBox);
this.Content = myStackPanel;
}
Best regards,
Quaneu
Hallo zusammen,
ich bin gerade dabei Daten in einem DatGrid zu gruppieren. Dazu benutze ich eine ListCollectionView und befülle die GroupDescriptions.
z.B.
public bool GroupByVariableName
{
get => _groupByVariableName;
set
{
_groupByVariableName = value;
GroupDescriptions.Clear();
if (_groupByVariableName)
{
GroupDescriptions.Add(new PropertyGroupDescription("Name"));
}
OnPropertyChanged(new PropertyChangedEventArgs(nameof(GroupByVariableName)));
}
}
Das Problem ist, dass der Aufruf "Add" auf GroupDescriptions sehr lange brauchen kann. Dies hat zur Folge, dass das GUI einfriert. Um dies zu verhindern, würde ich gern diesen Aufruf async auszuführen. Jedoch geht dies leider nicht, wenn die ListCollectionView schon gebunden ist (Thread Probleme...).
Daher meine Frage kennt ihr einen sauberen Weg GroupDescriptions eine PropertyGroupDescription hinzuzufügen ohne das das GUI einfriert?
Schöne Grüße
Quaneu
P.S. An VirtualizingPanel.IsVirtualizingWhenGrouping habe ich schon gedacht 😃 Es liegt wirklich nur am Add(...)
Es gibt eine DLL "X" in ihr sind zwei DLLs embedded. Wenn diese gebraucht werden, "entpacke" ich diese DLLs.
Dies wird deshalb gemacht da die "X" DLL beim Programmstart geupdatet werden kann und ich nicht n-DLLs kopieren will, sondern nur eine. Damit stelle ich auch sicher, dass das gesamte Packet zusammen passt.
Danke für die Info.
Wenn es hier ein Problem gibt, dann hast Du wahrscheinlich was falsch gemacht.
Wie gesagt, dass Problem sind z.B. alle statischen Klassen, die von WPF initialisiert werden (z.B. Application.Current). Diese sind in der AppDomain alle nicht initialisiert.
Warum Du "DLLs löschen willst, wenn sie ihre Arbeit erledigt haben" erschließt sich mir nicht.
Da ich die DLLs entpacke wollte ich sie auch wieder aufräumen. D.h. der Ordner soll nach dem Durchlauf so sein wie davor.
Hallo zusammen,
ich würde gerne wissen ob bzw. wie man folgendes Problem lösen könnte.
Ich habe eine exe (WPF) die eine DLL verwendet, diese kann vor der ersten Benutzung der DLL geupdatet werden, wenn die exe eine neuere Version findet. Die DLL wiederrum benutzt zwei weitere DLLs (eine ist Mixed Mode) die sie "entpackt" und verwendet (es wird dagegen implementiert).
Ich würde jedoch diese zwei DLLs wieder löschen wollen, wenn sie ihre Arbeit getan haben. Und hier finde ich einfach keinen Weg.
Ich habe es schon mit einer eigenen AppDomain probiert, da man Assemblies nicht einzeln entladen kann, jedoch kam es hier immer wieder zu Problemen... z.B. Application.Current ==null.
Gibt es hier auch eine andere Möglichkeit bzw. Lösungsansatz?
Schöne Grüße
Quaneu
Ich hab das Problem gefunden. Es lag nicht an der Architektur und wohl auch nicht am async / await, bzw. nur indirekt.
Hier ein Beispiel Code (hier habe ich auf Architektur verzichtet 😄)
<Window x:Class="Sample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Sample"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListBox Grid.Row="0" ItemsSource="{Binding Names, Mode=OneTime}"/>
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
<Button HorizontalAlignment="Right" Content="WorkAsync" Click="Button_Click" Margin="2"/>
<Button HorizontalAlignment="Right" Content="AddSingleName" Click="Button_Click_1" Margin="2"/>
</StackPanel>
</Grid>
</Window>
using System.Collections.ObjectModel;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
namespace Sample
{
public partial class MainWindow : Window
{
private readonly object _itemsLock;
public MainWindow()
{
_itemsLock = new object();
Names = new ObservableCollection<string>();
BindingOperations.EnableCollectionSynchronization(Names, _itemsLock);
DataContext = this;
InitializeComponent();
Names.CollectionChanged += Names_CollectionChanged;
}
private void Names_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
var listCollectionView = ((ListCollectionView)CollectionViewSource.GetDefaultView(Names));
}
public ObservableCollection<string> Names { get; }
private async void Button_Click(object sender, RoutedEventArgs e)
{
await Task.Run(() => HeavyMethod());
}
internal void HeavyMethod()
{
for (int i = 0; i < 3; i++)
{
Thread.Sleep(1000);
AddName($"Name_{i}");
}
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
AddName("SingleName");
}
private void AddName(string name)
{
lock (_itemsLock)
{
Names.Add(name);
}
}
}
}
Drückt man erst auf WorkAsync und danach auf AddSingleName kommt es zur Exception. WorkAsync kann man aber beliebig oft drücken.
Das Problem macht folgende Zeile
var listCollectionView = ((ListCollectionView)CollectionViewSource.GetDefaultView(Names));
Ohne diese läuft es immer... Leider verstehe ich es aber immer noch nicht 🤔
Schöne Grüße
Quaneu
Ich habe jetzt eine Lösung gefunden jedoch würde ich gern verstehen wie dieser Fehler zustande kommt.
Meine Lösung:
Wenn man diese AsyncObservableCollection benutzt
http://www.thomaslevesque.com/2009/04/17/wpf-binding-to-an-asynchronous-collection/
und
BindingOperations.EnableCollectionSynchronization(LogEntries, _itemsLock);
entfernt klappt es wie erwartet. Aber wie schon gesagt, wenn jemand weiß woran es liegt wäre ich sehr dankbar.
Schöne Grüße
Quaneu
Hallo MrSparkle,
das sieht vielleicht nur so aus. Es ist (bzw. sollte) nach MVVM gebaut sein.
Es gibt die UI, dann meine ViewModels und meine DatenObjekte. Man kann hier ischer noch einiges schönes machen, jedoch denke ich, dass dies nicht mein Problem verursacht. Aber ich werde nochmals einen Blick drauf werfen. Daher Danke für den Hinweis 😃
Schöne Grüße
Quaneu
Hallo Abt,
vielen Dank für deine Hinweise. Task.Run und async void habe ich gleich mal korrigert.
Könntest Du mir vielleicht sagen, was falsch implementiert ist? Wenn ich in meinem Beispiel nämlich ConfigureAwait(false) einbaue bekomme ich schon Fehler beim "ersten" Update.
Schöne Grüße
Quaneu
Hallo zusammen,
ich habe ein Problem mit einer ObservableCollection, die aus einem anderen Thread aktualisiert werden soll. Hierzu verwende ich BindingOperations.EnableCollectionSynchronization.
private readonly object _itemsLock = new object();
public Logger(string logPath)
{
LogPath = logPath;
LogEntries = new ObservableCollection<LogEntry>();
BindingOperations.EnableCollectionSynchronization(LogEntries, _itemsLock);
}
public void AddInfo(string message)
{
lock (_itemsLock)
{
Log(message, LogConstants.Info);
}
}
Diese Klasse wird im MainThread angelegt.
Das Aktualiseren in einem anderen Thread klappt. Jedoch wirft jeder Update, der danach stattfindet eine Exception, wenn dieser nicht in einem anderen Thread stattfindet.
Fehlermeldung:
System.NotSupportedException: 'Von diesem CollectionView-Typ werden keine Änderungen der "SourceCollection" unterstützt, wenn diese nicht von einem Dispatcher-Thread aus erfolgen.'
Das Updaten mache ich wie folgt:
private void ExecuteOpenPackage(object packageFile)
{
OpenPackage(packageFile as string);
}
private async void OpenPackage(string packageFile)
{
var openPackageResult = await OpenPackageAsync(Logger, packageFile);
}
private static Task<OpenPackageResult> OpenPackageAsync(Logger logger, string packageFile)
{
return Task<OpenPackageResult>.Factory.StartNew(() =>
{
// Lange Operation
logger.AddInfo("test");
return null;
});
}
Kann mir jemand sagen was ich falsch mache? Sobald ich eben den Task starte kann ich die Collection nicht mehr ohne Task updaten.
Schöne Grüße und vielen Dank
Quaneu
Hallo herbivore,
vielen Dank für deine Hilfe.
Mein Beispiel sollte folgenden Fall abdecken:
Ein Wort muss aus den Bestandteilen A,B und C bestehen, wobei man nur ein oder zwei Bestandteile wählen darf, dies aber beliebig oft. Jedoch mit der weiteren Einschränkung, dass die Reihenfolge beachtet werden soll. D.h. wenn ich 2 Bestandteile wähle, darf z.B. kein Element aus B vor denen aus A kommen usw.
Das bauen des Regexes ist nicht das Hauptproblem, sondern eher der Regex selbst. Wenn es nur diese Möglichkeit gibt, muss ich testen ob dies noch möglich ist, da z.B. A aus 6000 Wörtern besteht B hat mind. genau soviel usw.. dadurch würde der Regex extrem "lang" werden. Aber ich probier es mal im Kleinen.
Schöne Grüße und vielen Dank
Quaneu
P.S. Danke für dein Regex-Lab ist wirklich super und hat mir schon oft sehr weiter geholfen👍
Hallo zusammen,
ich würde gern eine Art Choice in Regex formulieren. Leider schaffe ich dies nicht 100%.
Z.B. Soll der Name aus A, B oder C bestehen, wobei A, B oder C wieder ein Regex sein kann. Wenn es nur einen Treffer geben soll, also Choice min=1 max=1 ist, habe ich eine Lösung "(A+|B+|C+)".
Komplizierter wird es wenn max z.B. 2 ist und dieser öfter treffen soll.
Hier ein konkreteres Beispiel:
A = [a|b|c], B = [d|e|f], C= [g|h|i] und der Name soll "adgbeh" sein.
Wenn ich nun folgenden Regex benutzte "((([a|b|c])+|[d|e|f])+|([g|h|i])+){1,2})*" sagt mir dieser, dass der Name gültig ist, aber meine Captures sind nicht so, wie ich sie brauche. In diesem Fall "ad gb eh". Das Problem dabei ist jedoch "gb". Es soll nämlich die Reihenfolge der Elemente berücksichtigt werden und g kommt nach dem b. Mein Ziel ist es, folgende Captures zu erhalten "ad g be h".
Ich habe es schon mit Lookaround probiert, jedoch ohne Erfolg.
Hätte jemand eine Idee, wie ich dieses umsetzen kann?
Schöne Grüße
Quaneu
Entschuldige bitte meine späte Antwort. Aber leider war es mir nicht möglich, früher zu antworten.
Danke für deinen Hinweis. Dies klappt jetzt ganz gut.
Hallo zusammen,
ich will mit einem Regex prüfen, ob z.B. aus drei Gruppen mindestens eine trifft.
Hier ist ein Beispiel: "1([abc]* | [def]* | [ghi]*){1}2"
D.h. ich würde gerne prüfen ob [abc], [def] oder [ghi] mindestens einmal trifft. Dies klappt mit diesem Regex auch fast, jedoch trifft er auch "12" und dies soll verboten sein.
Wie kann man dies über Regex abbilden?
Schöne Grüße und vielen Dank
Quaneu
Hallo herbivore,
vielen vielen Dank für deine Antwort 🙂. Du hast Recht. Ich hab mir gestern zwar den Match bzw. die Groups in dem Match immer wieder angeschaut, aber die Captures nicht mehr, da die Group "2" als Value nur "c" hat. Kann es sein das dies auch "spezielles" Feature des .Net Regex ist?
Schöne Grüße und nochmals vielen Dank
Gennaro
P.S.
Dein Tool ist wirklich super 👍 👍 👍 kommt jetzt immer zum Einsatz!
Hallo zusammen,
ich habe eine Frage zu Regex in Bezug auf Matches.
Wenn ich folgenden Namen "abc" und diesen mit dem Regex "^(?<1>[a|b])*(?<2>[b|c]){2,}$" prüfen will. Dann bekomme ich als Ergebnis ein Match, jedoch mit folgender Aussage:
Start Length
Match 1: abc 0 3
Group "1": a 0 1
Group "2": c 2 1
Das "b" geht verloren bzw. wird nicht als Treffer in Group "2" angezeigt. Ich bräuchte jedoch als Resultat folgendes:
Start Length
Match 1: abc 0 3
Group "1": a 0 1
Group "2": b 1 1
Group "2": c 2 1
Was nicht reichen würde, ist
Start Length
Match 1: abc 0 3
Group "1": a 0 1
Group "2": bc 1 2
Weiß jemand wie ich den Regex dazu bringe, mir dies auszugeben?
Vielen Dank und schöne Grüße
Quaneu
Entschuldige bitte. Ja ist ein Integrationstest.
Ich hab es deshalb so gelassen, da ja mit Hilfe von MsTest auch automatisch aufgeräumt wird usw.. Wenn ich die Dateien in ein anderes Verzeichnis schreibe, muss ich das alles machen.
Aber Du hast mich gerade auf eine Idee gebracht. Die exe liegt in dem TestsResults Ordner, d.h. ich kann die Angaben für die Dateien relativ setzten, d.h. somit taucht das Datum nicht mehr im Pfad auf.
VIELEN VIELEN DANK.
Manchmal hilft es einfach, drüber zu reden 😃
Kein Problem.
Also der Test ruft mein Tool auf, dass eine Datei in eine andere Umwandelt und prüft ob die geschriebene Datei gültig ist. Das Resultat der Umwandlung wird in TestResults... geschrieben und anschließend eben gegen eine Referenzdatei verglichen. Dadurch, dass eben wie unten erwähnt, in den Pfaden ein Datum vorkommt (als Kommentar in der geschrieben Datei), kann es keine gültige Referenzdatei geben, bzw. schlägt der Test an.
Ich schreibe eine Datei, in der z.B. folgendes steht
// LogPath: C:\Users\ToolName\TestResults\Deploy_User 2018-04-14 11_43_06\Out\Outputs_AddressImportFiles\Diab_5.8.0.txt
Dadurch, das 2018-04-14 11_43_06 im Pfad vorkommt, kann ich keine Referenzdatei erstellen, da sich das Datum je immer ändert, bzw. schlägt eben der Test fehl.
aber vielen Dank für deine Hinweise.
Also bei mir sieht er immer so aus: Deploy_<User> <Datum>
Das Problem ist, dass ich Dateien schreibe, in denen als Kommentar z.B. steht, wie der Log oder der Destination Pfad lautet. In diesen ist somit auch das Datum. Da ich die geschrieben Dateien gegen Referenzdateien prüfe (binär) bekomme ich eben falsche Resultate.
Ich könnte natürlich "seams" einbauen, aber dann teste ich schon wieder "weniger.
Hallo zusammen,
ich würde gerne den Namen der Folder in TestResults ändern.
Bisher werden diese ja immer unter "...\TestResults\Deploy_<User> <Datum>" abgelegt. ich würde gerne das Datum weglassen, da dies in manchen Tests Probleme macht.
In der Local.runsettings habe ich nur Möglichkeit ResultsDirectory zu beeinflussen, aber dies Hilft mir nicht weiter.
Hat jemand eine Idee wie man das Datum weglassen kann? Ich benutzt VS2017 mit MsTest und/ oder ReSharper.
Schöne Grüße und vielen Dank
Quaneu
VIELEN VIELEN DANK.
Mit IsSharedSizeScope klappt es wunderbar. Jetzt ist es schöner als ursprünglich angedacht 👍 👍 👍
Und nochmals vielen Dank 😃
Ich probiere es gerade mit IsSharedSizeScope. Wenn dies klappt, wäre es für mich die schönste Lösung. Aber ich habe ja jetzt noch ein paar Alternative 😉
Hallo Palladin007,
vielen Dank für deine Hinweise. Ich werde es gleich mal ausprobieren
Das man es über CodeBehind lösen muss, war mir auch bewusst. Ich meinte mit XAML eher, dass ich in diesem den Content bereitstelle, um den das Grid erweitert werden soll. Z.B
<misc:BasicInformationUserControl.FurtherContent>
<ItemsControl>
<TextBox Text="A" Grid.Row="0" Grid.Column="0"/>
<TextBox Text="B" Grid.Row="0" Grid.Column="1"/>
</ItemsControl>
</misc:BasicInformationUserControl.FurtherContent>
Leider bekomme ich eben mit diesem Beispiel PropertyChangedCallback von FurtherContent immer ein ItemsControl ohne Items...
Schöne Grüße
Quaneu
Hallo zusammen,
eine Frage kommt selten alleine...
Ich probiere schon seid Stunden folgendes Problem zu lösen. Ich habe ein UserControl, in dem ein Grid definiert ist mit z.B. 3 Zeilen und 2 Spalten. Nun würde ich an den Stellen, an dem ich das UserControl benutze das Grid so erweitern, dass ich Zeilen hinzufügen kann, die dann die selben Spaltenbreiten haben, wie das Grid im UserControl. Leider finde ich keine Möglichkeit dies umzusetzen.
Ich habe es schon mit einem DependencyProperty "FurtherContent" probiert, das ich setzten kann und im PropertyChangedCallback das Grid dynamisch erweitere.
Doch leider klappt dies nicht. Wenn z.B. "FurtherContent" vom Typ Grid ist so kommt im PropertyChangedCallback ein Grid an, dass nie Children hat, obwohl im XAML welche definiert sind.
Schöne Grüße
Quaneu
Hallo Th69,
vielen Dank für deine Links. Jetzt ist mir einiges klarer.
Schöne Grüße
Quaneu
Hallo zusammen,
ich habe ein "eigenes" Control, dass von GroupBox ableitet.
<GroupBox x:Class="Test.OwnGroupBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<GroupBox.Style>
<Style TargetType="{x:Type GroupBox}">
<Setter Property="Margin" Value="2"/>
</Style>
</GroupBox.Style>
</GroupBox>
Wenn ich nun diese GroupBox wie folgt benutze
<UserControl x:Class="Test.BasicInformationUserControl"
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:controls="clr-namespace:Test"
mc:Ignorable="d" x:Name="_basicInformationUserControl"
x:Uid="BasicInformationUserControl">
<controls:OwnGroupBox Header="General" x:Uid="GeneralGroupBox">
<TextBlock Text="Status" x:Name="xxx"/>
<ContentPresenter Content="{Binding Height, ElementName=_basicInformationUserControl}"/>
</controls:OwnGroupBox>
</UserControl>
bekomme ich diesen Fehler> Fehlermeldung:
Cannot set Name attribute value 'xxx' on element 'TextBlock'. 'TextBlock' is under the scope of element 'OwnGroupBox', which already had a name registered when it was defined in another scope.
Und das Binding im ContentPresenter geht auch nicht. Ersetze ich nun controls:OwnGroupBox durch GroupBox, bekomme ich keinen Fehler mehr und das Binding klappt.
Leider verstehe ich nicht wieso eine Ableitung dies zur Folge hat. Hätte jemand eine Idee, warum dies so ist.
Viele Grüße
Quanue
Hallo MrSparkle,
mit Validierung ist hier z.B. gemeint, ob der User etwas an der Eingabemaske geändert hat. Wenn er etwas geändert hat, soll eine Abfrage kommen, ob er speichern oder die Eingaben verwerfen will. Geht jedoch beim speichern etwas schief, soll kein neuer Knoten (hier TreeViewitem) selektiert werden.
Im ViewModel für meine TreeViewitems geht es leider nicht, bzw. wüsste ich nicht wie. Daher feuert jedes TreeViewitemViewModel ein Event wenn es selektiert wird und ein Controller hört auf diese und macht bisher auch die Validierung. Mein Problem ist nur das Unterbinden eines TreeViewItems Wechsels.
Schöne Grüße
Quaneu
Hallo zusammen,
ich habe folgendes Problem.
Wenn in einem TreeView ein anderer Knoten selektiert wird, soll eine Überprüfung stattfinden, die eventuell eine Änderung des Knotens unterbinden soll. Dazu sei gesagt, dass wenn die Überprüfung eine Änderung untersagt, eine MessageBox auf geht, in der der User abspeichern, oder die Änderungen verwerfen kann.
Ich habe es schon mit einem PreviewMouseLeftButtonDownCommandProperty Behavior probiert, dass ich auf dem TreeView registriere.
Jedoch habe ich hier ein merkwürdiges Verhalten festgestellt. Ich setzt, je nachdem ob der User speichern will oder nicht, e.Handled auf false oder true (im PreviewMouseLeftButtonDown Event).
Dies funktioniert leider nur, wenn keine MessageBox auf geht. Geht eine auf, ist es so, als ob e.Handled immer auf false gesetzt wird. Leider verstehe ich nicht wieso dies so ist...
Für andere Lösungen oder einer Erklärung der besagten Verhaltens, wäre ich sehr dankbar.
Schöne Grüße
Quaneu
Ich habe jetzt mal alles relativ positioniert, aber eben noch mit Overflow. Leider scheint dies den Browser zu "iterieren", d.h. das Springen klappt nicht mehr, wenn ich Overflow auf Auto setze.
Weiß jemand wie man overflow benutzt und das Springen im Browser ermöglicht?
Ich dachte da ich alles mit % bzw. vh benutzte sollte es keine Probleme geben... Da ich aber erst seid kurzem Html mache, wurde ich wohl heute eines Besseren belehrt.
Wenn jedoch noch jemand einen Hinweis habe wie ich mein Problem anders lösen kann, bin ich für alles aufgeschlossen 😉
Und nochmals Danke für die Hilfe 👍
Ich habe den Übeltäter gefunden:
#_9359f5c9607546909d0a55812fd07445 {
position: fixed;
top: 2%;
left: 20%;
overflow-x: auto;
height: 95vh;
width: 80%;
background: #DAECF5;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
}
Wenn man position: fixed und overflow-x: auto wegnimmt, klappt es...
Jetzt frag ich mich aber, wie Löse ich diesen Konflikt...