Laden...

Forenbeiträge von c#nup Ingesamt 19 Beiträge

15.10.2020 - 13:51 Uhr

Danke für den Hinweis dannoe. Die Methode CompareOrdinal() ist die, die ich brauche. Dennoch frage ich mich, nach welcher Regel Compare() sortiert - gerade bei positiven und negativen Zahlen als strings. Ein Blick in den Quellcode von String.Compare() führt zu einem PInvoke


[System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Process)]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SuppressUnmanagedCodeSecurity]
        private static extern int InternalCompareString(IntPtr handle, IntPtr handleOrigin, String localeName, String string1, int offset1, int length1,
                                                                              String string2, int offset2, int length2, int flags);

Weiß jemand woher InternalCompareString() kommt und was es macht?

15.10.2020 - 09:25 Uhr

Hallo zusammen,

gegeben ist ein DGV mit einer TextBoxColumn. In der Spalte stehen die Werte "1", "-1", und "2" drin. Durch das Klicken auf den Spaltenkopf werden die Werte sortiert. Aufsteigende Sortierung (von oben nach unten): "1", "-1","2". Absteigende Sortierung: "2", "-1", "1".

Ich hätte erwartet, dass hier zeichenweise sortiert wird, also "-", "1", "2", dem ist aber nicht so. Nach welcher Regel wird hier sortiert?

11.09.2019 - 16:27 Uhr

Hallo liebe SharePoint-Freunde,

Sharepoint Online, csom, c# ...

Zum Problem:
Gegeben ist eine Sharepoint Liste mit einer Spalte namens Datum, vom Datentyp Datum. In diese Liste möchte ich folgende Einträge einfügen:

  • 01.01.2001,
  • I CAUSE TROUBLE
  • 03.03.2003
    Als Ergebnis will ich im Browser folgendes sehen:
  • 01.01.2001
  • 03.03.2003
    Das ganze will ich mit möglichst wenigen Aufrufen - am besten mit einem einzigen Aufruf - von clientContext.ExecuteQuery() erreichen;

Wie ihr euch denken könnt löst Sharepoint bei "I CAUSE TROUBLE" eine Exception aus, weil das Format nicht passt, und bricht die Verarbeitung an dieser Stelle ab.

Die triviale Lösung - je ein ExecuteQuery() für jedes Feld, das ich beschreibe aufzurufen - drückt bei realen Datenmengen die Performance und ist deshalb nicht akzeptabel.

Zur Frage:

  • Bietet csom eine Möglichkeit die Daten clientseitig zu validieren, sodass ich den Typkonflikt zwischen "I CAUSE TROUBLE" und dem Feldtyp "Datum" erkennen kann bevor ich den ganzen Datensatz mit ExecuteQuery() an Sharepoint sende?

oder

  • Kann man Sharepoint anweisen die auftretende Exception serverseitig zu behandeln und mit dem Schreiben des nächsten Eintrags fortzufahren?

Danke für eure Hilfe.

20.02.2019 - 21:38 Uhr

Hallo camelord, ich habe weder mit vue.js noch mit mongodb gearbeitet, deshalb kann ich dir nichts konkretes sagen.

Bei der Arbeit an Web-Anwendungen hänge ich mich ganz gerne mit dem VisualStudio-Debugger an den IIS-Prozess der Webanwendung an, während die Anwendung ganz normal im IIS läuft und auf vorgesehen Weise (z.B. über Browser) angesprochen wird. So kann ich unter realen Bedingungen sehr genau nachvollziehen wo was schief geht. Das geht natürlich nur, wenn die Anwendung in einem VisualStudio-Projekt entwickelt wurde.

Für Details siehe hier. Beachte, dass der Prozess der Anwendung erst dann im Prozessbrowser erscheint, wenn die Anwendung vor kurzem angesprochen wurde und nicht direkt nach dem Start der App im IIS. Und die App sollte natürlich im Debug Modus gebaut werden.

20.02.2019 - 20:58 Uhr

hier noch die andere .cs

20.02.2019 - 20:55 Uhr

Ok, die zip mit den Projekten ist zu groß, deshalb hänge ich hier die zwei relevanten .cs Dateien an.

  1. Ich habe mir ein VSIX Projekt namens "MeinCommand" angelegt wie zB hier beschrieben. In diesem VSIX Projekt habe ich ein Command "Mein Command" eingefügt. Die entsprechende Datei "MeinCommand.cs" ist im Anhang. Zu beachten sind die Includes:
using System.Runtime.InteropServices;
using EnvDTE;

und das was in der Methode Execute() passiert:

         private void Execute(object sender, EventArgs e)
        {
            DTE dte = (DTE)Marshal.GetActiveObject("VisualStudio.DTE.15.0"); // bei VisualStudio 2017
            //DTE dte = (DTE)Marshal.GetActiveObject("VisualStudio.DTE.14.0"); // bei VisualStudio 2015
            Globals globals = dte.Globals;

            string s = "";

            try
            {
                s = (string)globals["meinGlobalVar"];
                MessageBox.Show("Der Wert meiner globalen Variable ist: " + s);
            }
            catch(Exception ex)
            {
                globals["meinGlobalVar"] = "los gehts";
                MessageBox.Show("Meine globale Variable wird mit 'los gehts' initialisiert");
            }
        }

Diese Extension erweitert mein VisualStudio um die Option "Invoke MeinCommand" im "Extras" Menü (in der englischen Version ist es das Tools Menü). Durch einen Click auf diese Option wird die Methode "Execute" ausgeführt.

  1. Nachdem ich die VS Extension compiliert und installiert habe, habe ich eine stinknormale Konsolenanwendung angelegt - siehe Program.cs. Einziger relevanter Inhalt:
  static void Main(string[] args)
        {
            DTE dte = (DTE)Marshal.GetActiveObject("VisualStudio.DTE.15.0");
            Globals globals = dte.Globals;

            string s = globals["meinGlobalVar"];

            MessageBox.Show(s);

            globals["meinGlobalVar"] = "zweiter Schritt";
        }

Diese Konsolenanwendung starte ich direkt aus VS.

  1. Es ist nur eine VS Instanz offen und zwar die mit der Konsolenanwendung. Die Konsolenanwendung ist nicht gestartet. Durch einen Click auf "Invoke MeinCommand" lege ich in der VS Extension im Globals Interface das Name/Wert Paar namens "meinGlobalVar" und initialisiere es mit dem Wert "los gehts". Nun starte ich die Konsolenanwendung und und rufe hier das Globals Interface (nach meinem bisherigen Verständnis gehört es zur aktiven VisualStudio Instanz) ab, genauer das gerade eben angelegte Name/Wert Paar "meinGlobalVar" und OH WUNDER mein string s bekommt den Wert "los gehts". Dann weise ich dem Name/Wert Paar den string-Wert "zweiter Schritt" zu und klicke wieder auf das Command "Invoke MeinCommand" - OOOH, NOCH EIN WUNDER in der VS Extension kommt der gerade eben gesetzte Wert "zweiter Schritt" zum Vorschein.

Das ist im Grunde die Funktionalität auf die ich aus bin - nur solle statt Strings beliebige Objekte geteilt werden.


Auf das DTE.Globals Interface bin ich erst heute im Tagesverlauf gestoßen. So ganz bin ich da noch nicht durchgestiegen, aber es scheint so ziemlich das zu sein, was ich mir als Lösung für mein Problem vorstelle. Mir ist aber noch nicht gelungen beliebige Objekte über dieses Interface hin und her zu schieben (so wie die strings im obigen Beispiel).

Für eure konstruktive Beiträge bin ich weiterhin dankbar.

20.02.2019 - 13:59 Uhr

@Abt
Ich versuche mal nachher an einem Beispiel zu demonstrieren um was es mir geht. Vielleicht wird es dann klarer.

@Th69
Es ist halt so gefordert, dass die Daten an dieser Stelle verfügbar sein müssen. Der Entwickler des Forms soll zu dem Zeitpunkt wenn er ein Control plaziert auch die betreffenden Eigenschaften händisch festlegen. Dabei soll er aus einer festgelegten Menge an Werten auswählen. Die Werte werden bei bei jedem Bearbeitungsvorgang, von einem anderen System neu geladen.

20.02.2019 - 12:02 Uhr

Hi Abt,

die Extension implementiert ein Command, einen Button in der Werkzeugleiste von VS. Wird dieser Button gedrückt, wird eine Liste von Strukturen aus einer nicht statischen Quelle geladen, wobei jede Struktur aus einem string "Name" und einer List<string> "Werte" besteht. Der Ladevorgang für diese Strukturen, die geladenen Strukturen und einiges mehr, sind implementiert in einem Singleton-Objekt den ich in meinem Eingangspost "datenManager" genannt habe. Das ganze geschieht unabhängig davon ob und welche Art von Projekt in VS gerade bearbeitet wird. Bis hierhin Funktioniert alles wie gewünscht.

Eine Anwendung für die geladenen Strukturen soll sein:

  1. Man lege eine Control-Klasse an, die von einem beliebigen Windows.Forms Control erbt und versehe diese Klasse mit zusätzlichen Eigenschaften e1 und e2.
  2. Man erstelle ein neues Form-Projekt in VS, ziehe eines dieser "eigenen Controls" auf den Form und gehe zu den Eigenschaften e1 und e2 im Eigenschaften-Fenster.
  3. An dieser Stelle werden die geladenen Daten aus dem "datenManager" benötigt. Im einfachsten Fall erhalten e1 und e2 im Eigenschaftenfenster Dropdowns mit den "Namen" der Strukturen und den dazu gehörenden Werten aus den List<string>.
    Das programatische Anlegen von Dropdowns für Eigenschaften im Eigenschaftenfenster funktioniert soweit (- zumindestens im einem Entwurf, aber an dieser Stelle muss ich später noch mehr arbeiten).

Mein Problem ist, dass ich zum Zeitpunkt 3. nicht auf den "datenManager" zugreifen kann, den ich bei der Ausführung des Commands initialisiert habe. Aus dem Bauch heraus stelle ich mir eine Lösung vor, bei der ich das "datenManager"-Objekt nach der Initialisierung in einem "VisualStudio-globalen" Bereich ablege und von dort abrufe. Ich bin da aber sehr ahnungslos und deshalb offen für andere Vorschläge.

19.02.2019 - 14:36 Uhr

Hallo community,

ich habe eine Visual Studio Extension (VSIX) mit einem Command geschrieben. Auf Knopfdruck passiert im Command im Wesentlichen folgendes:

DatenManager datenManager = new DatenManager();
DatenManager.holDaten();

Dieses Command kann vom VS Nutzer zu einem beliebigen Zeitpunkt ausgelöst werden - direkt nach dem Start, noch bevor ein Projekt ausgewählt oder angelegt wurde, oder auch Mitten in der Arbeit an einem Projekt.

Nun möchte ich das datenManager-Objekt innerhalb eines Projekts zugänglich machen, sodass der Programmierer zu Lebzeiten der VS-Instanz die im Datenmanager enthaltenen Daten nutzen kann.

Sinngemäß also sowas:

VisualStudioInstance.GlobalObjectCache.add(datenManager) // das würde noch im Command passieren
...
...
try{
DatenManager dm = (DatenManager)VisualStudioInstance.GlobalObjectCache.GetObject("datenManager")
}
// ab hier wird dann innerhalb eines Projekts mit den Daten aus dem Datenmanager gearbeitet
...

Überall ist zu lesen, dass VS absolut erweiterbar und konfigurierbar ist, also gehe ich davon aus, dass es einen realen Gegenpart zu meinem erfundenen "VisualStudioInstance.GlobalObjectCache" geben muss.

Kann mich bitte jemand aufschlauen.

13.02.2019 - 16:58 Uhr
  1. Knoten rausfiltern
    Chrisrabe, wenn du den Knoten rausfiltern möchtest, dann kommentiere den von dir geposteten Codeabschnitt aus und setzte den folgenden Codeabschnitt direkt darunter:


TreeNode projectNode = (System.Windows.Forms.TreeNode)(resources.GetObject("projectTreeView.Nodes"));
TreeNode controlLoopsNode = null;

            foreach(TreeNode node in projectNode.Nodes)
            {
                if (node.Text.Equals("Control Loops"))
                {
                    controlLoopsNode = node;
                    break;
                }
            }

            if (controlLoopsNode != null)
            {
                projectNode.Nodes.Remove(controlLoopsNode);
            }

this.projectTreeView.Nodes.AddRange(new System.Windows.Forms.TreeNode[] { projectNode} );            


  1. Zu deiner Frage nach dem "woher":
    Der Umstand, dass du nirgends in dem dir zugänglichen Code eine Stelle findest an der ein TreeNode Objekt mit dem Text "Control Loops" angelegt wird und die sprechende Benennung des "resources"-Objekts in deinem Quelcode deuten darauf hin, dass an dieser Stelle irgendeine Bibliothek ausgelesen wird. Diese Bibliothek zu "öffnen" und dort die Baumstruktur zu ändern ist sehr warscheinlich nicht zielführend. Einige Gründe:
  • die Bibliothek kann verschlüsselt sein
  • die Baumstruktur ist in der Bibliotek nicht hartcodiert, sondern wird zur Laufzeit aus irgendwelchen anderen Parametern erzeugt
  • andere Programme greifen auf "projectTreeView.Nodes" zu und brauchen dort den "Control Loops" Knoten

Deshalb scheint mir, dass du dich für die Entfernung "Control Loops" Knotens mit dem von mir geposteten Code begnügen solltest.

Falls du dennoch in den Bibliotheken graben willst, dann hol dir das Programm ILSpy oder einen anderen .NET Decompiler und schau dir damit die deinem Programm beigefügten .dll Dateien an. Vielleicht wirst da fündig. Aber ich rate dir nichts an den dlls zu ändern.

13.02.2019 - 14:05 Uhr

Hallo chrisrabe,

grundsätzlich ist es durchaus ein möglicher Ansatz zu schauen wo die Daten herkommen und sie ggf. am Ursprung zu korrigieren. In deinem Fall liegt die Quelle der Daten außerhalb deines Einflussbereichs. Die Daten können in der dll statisch gespeichert sein, es kann aber auch sein, dass die dll einen Mechanismus enthält der die Daten zur Laufzeit aus dem Internet saugt - nur mal so ins blaue geraten.

Die Lösung für dein Problem liegt sehr warscheinlich in genau dem Codeabschnitt den du in deinem ersten Post gepostet hast. Setz an dieser Stelle einen Breakpoint und schau dir

resources.GetObject("projectTreeView.Nodes")

im Debugger an. Warscheinlich wird es der Knoten "Project - New Project*" sein, an dem dann die anderen Knoten hängen (schau dir die Nodes Eigenschaft an).

12.02.2019 - 13:29 Uhr

Danke!

11.02.2019 - 15:01 Uhr

Hallo Th69, ich hoffe das funktioniert jetzt wie beabsichtigt.

In der propjekte.zip findest du je eine zip mit dem Dll-Projekt für das UserControl und dem Form-Projekt wo dieses UserControl eingebunden ist. Wie in Punkt 3 meines Eröffnungsposts beschrieben, habe ich im Dll-Projekt die Events "DragDrop" und (zu Vorführzwecken) "DoubleClick" der Textboxen behandelt und in den Handlermethoden je ein eigens definiertes Event des UserControls ausgelöst. Die Events des UserControls werden dann im Form behandelt. Die Crux ist nach wie vor, dass das DragDrop Event nicht geht (das DoubleClick Event funktioniert wie gewünscht).

11.02.2019 - 10:25 Uhr

Hat niemand eine Idee?

Habe ich das Problem unklar beschrieben, oder ist es eher eines dieser Randgruppenprobleme? 😛

07.02.2019 - 15:31 Uhr

Hallo Community,

folgende Problemstellung:
Ich habe ein WinForm, darin ein TableLayoutPanel, 1 Zeile, 2 Spalten. In der linken Spalte sitzt eine Listbox mit string-items. In der rechten Spalte wird zur Laufzeit, aus einer dll, ein UserControl geladen. Das UserControl enthält Textboxen und andere Controls. Ziel ist die Strings aus der Listbox zu draggen und in die Textboxen ( die auf dem UserControl sitzen) zu droppen - wie ihr euch denken könnt scheitere ich genau daran, das DragDrop Event der Textboxen und des UserControls löst nicht aus.

Versucht habe ich unter anderem:

  1. ein neues WinForm Projekt angelegt, wo das UserControl sich im selben Projekt wie das Form befindet - das UserControl wird also wird nicht zur Laufzeit aus einer dll geladen. Ergebnis: D&D funktioniert wenn ich die "AllowDrop" Eigenschaft des UserControls auf false setze und die "AllowDrop" Eigenschaft der TextBox auf true.
  2. In der eingangs beschriebenen Aufstellung, also mit Laden des UserControls aus der dll, habe ich die Events DragEnter und DragLeave der Textboxen (aus dem UserControl) behandelt. Ergebnis: diese Events funktionieren wie erwartet. Wenn ich während dem Draggen mit der Maus in eine Textbox reinfahre wird das DragEnter Event ausgelöst, beim Verlassen der Textbox dann das DragLeave Event.
  3. Ich habe das DragDrop Event der Textboxen im UserControl-Projekt an das UserControl weiter geleitet. Dazu habe das DragDrop Event der Textboxen behandelt und in der Handler-Methode ein eigenes Event des UserControls ausgelöst. Ergebnis: das DragDropEvent der Textboxen löst nicht aus.
  4. Mithilfe der Events DragEnter, DragLeave und MouseUp der Textboxen habe ich versucht "ein eigenes" DragDrop Event zu implementieren. Prinzip: wenn MouseUp nach DragEnter und vor DragLeave ausgelöst wird, dann führe DragDrop Funktionalität aus. Ergebnis:
  • wenn das Event MouseDown (Beginn des Drag-Vorgangs) auf der Listbox ausgelöst wird, dann wird auf dem UserControl und seinen Textboxen kein MouseUp Event ausgelöst wenn ich die Maustaste wieder loslasse.
  • wenn das MouseDown Event auf dem UserControl ausgelöst wird und die Maustaste anschließend wieder auf dem UserControl loslasse, wird das MouseUp Event ausgelöst
    ( - Texte zwischen zwei Textboxen innerhalb des UserControls kann ich trotzdem nicht Dragdroppen da das DragDrop Event der Textboxen nicht auslöst).

Es wundert mich, dass die DragEnter und DragLeave Events der Textboxen wie erwartet funktionieren, während das DragDrop Event spinnt. Meine Vermutung ist, dass das die Fehlfunktion von DragDrop irgendwie mit dem Verhalten des MouseUp Events, wie in 4. beschrieben, zusammenhängt.

Ich bitte um Rat.

30.01.2019 - 07:58 Uhr

Danke für die Antwort weismat. Mittlerweile bin ich auf MSBuild.ILMerge.Task gestoßen. Es ist ein Nuget-Packet, das einen ILMerge Task ins Projekt integriert um alle dll's zu mergen. Tolle Sache!

24.01.2019 - 09:00 Uhr

Hallo Comunity,

ich habe 2 dll's. Lib.dll enthält einige Klassen, Product.dll ist eine COM-Komponente die von einer Drittsoftware genutzt wird. Zur Laufzeit arbeitet die Product.dll mit Objekten von Klassen die in der Lib.dll definiert sind. Ich habe vollen Zugang zu beiden Entwicklungsprojekten in Visual Studio, würde aber in der Product.dll ungerne Code schreiben.

Wenn ich deploye, muss ich die Lib.dll ins Verzeichniss der Drittsoftware (die die Product.dll aufruft) legen, anderenfalls wird die Lib.dll nicht gefunden und es kommt zum Absturz. Das geht zur Entwicklungszeit, jedoch nicht im Produktiveinsatz. Was auch nicht geht, ist die Klassen, die in der Lib.dll sind in die Product.dll zu copypasten.

Im VS Projekt der Product.dll ist die Lib.dll als Verweis eingebunden. In den Eigenschaften dieses Verweises gibt es die Option "Interoptypen einbetten" mit der Erklärung "Gibt an, ob in der Assembly definierte Typen in die Zielassembly eingebttet werden". Nach meinem Verständniss würde die Lib.dll mit dieser Option in die Product.dll integriert und ich bräuchte die Lib.dll nicht separat zu Deployen - das ist mein Ziel.

Wenn ich die "Interoptypen einbetten"-Option aktiviere und das Projekt erstelle, dann kommt es zum > Fehlermeldung:

Fehler BC31553: "Aus Assembly "Lib.dll" können keine Interoptypen eingebettet werden, da entweder das System.Runtime.InteropServices.ImportedFromTypeLibAttribute-Attribut oder das System.Runtime.InteropServices.PrimaryInteropAssemblyAttribute-Attribut fehlt." Ab hier stehe ich auf dem Schlauch. Trotz googlen ist mir nicht klar wo und wie ich diese Attribute setzen soll.

Also im Kern geht es mir darum beim erstellen der Product.dll die Lib.dll so einzubinden/einzubetten, dass die Lib.dll Inhalte in der Product.dll enthalten sind, ohne dass ich die Lib.dll mitschleppen muss.

Ich bitte um Rat.

07.12.2017 - 10:36 Uhr

Danke wcseller. Das Stichwort "Tree mit Spalten" bringt mich weiter.

>> Alternativ soll es noch käufliche Controls geben, die aber in diesem Fall nicht in Frage kommen...
>Warum eigentlich nicht - wozu das Rad immer wieder neu erfinden? Denkst du, Du bekommst das preiswerter hin?

Zum einen habe ich keine Budgetvollmachten und möchte nicht wegen dieser Kleinigkeit jetzt die Bürokraten aufscheuchen. Zum anderen müsste ich mich auch in ein käufliches Control erstmal ein wenig einarbeiten - mit einer Zeitersparnis rechne ich im konkreten Fall nicht.

06.12.2017 - 16:39 Uhr

Hallo Comunity,

vorab: DGV = DataGridView...

Mir steht eine Kniffelaufgabe bevor: gegeben ist ein existierender Form mit einem DGV in dem tabellarische Daten angezeigt werden. Ich muss diesen Form so umbauen, dass manche der Datensätze jetzt untergeordnete Datensätze haben können. Hier der Versuch einer Skizze von dem was rauskommen soll:

------------------------------------------------------------------------------------------------
| Nummer | Projekt                  | Verantwortlicher | Dauer | viele andere Spalten ...
------------------------------------------------------------------------------------------------
| 1            | mittleres Projekt    | Mayer                | 3        |
---------------------------------------------------------------------
| 2            | großes Projekt       | Müller                | 4        |
---------------------------------------------------------------------
| 3            | -- kleines Projekt 1 | Schmidt             | 2        |
---------------------------------------------------------------------
| 4            | -- kleines Projekt 2 | Kunz                 | 2        |
---------------------------------------------------------------------

Die Zeilen 1 und 2 befinden sich auf der gleichen Hierarchieebene. Die Zeile 2 ist untergliedert durch die Zeilen 3 und 4. Die Struktur der Datensätze ist über alle Hierarchieebenen identisch. Die unteren Ebenen müssen lediglich durch eine Art Pfeil und eine Einrückung gekennzeichnet werden.

Nach meinen bisherigen Recherchen kann die DGV-Klasse diese Untergliederung nicht leisten. Ein Ansatz wäre die DataGrid-Klasse (und den entsprechenden Control) zu nutzen - die soll diese Hierarchisierung können. Alternativ soll es noch käufliche Controls geben, die aber in diesem Fall nicht in Frage kommen...

Nun meine Fragen an euch:

  • Irre ich mich, und die Aufgabe kann doch mit einem DGV gelöst werden? Wenn ja, wie?
  • Wenn DGV nicht geht, ist DataGrid der richtige Ansatz oder kennt ihr bessere Lösungen?
  • Falls jemand schon vor einer vergleichbaren Aufgabe stand und Tips loswerden möchte, immer her damit.

Danke im Voraus!