Für WinForms Projekte (das glaube ich aus den verwendeten Klassen heraus lesen zu können) wird die Lokalisierung in der Regel über Ressourcen realisiert. Das ist eine auch vom WinForms-Designer unterstützte Variante. Lokalisierung bedeutet i.d.R. ja nicht nur das anpassen der Strings sondern oft auch eine Anpassung der Größen und Positionen einzelner Controls.
Wenn Du Deinen Weg weiterverfolgen möchtest, solltest Du dich auch mal mit der Schnittstelle IExtenderProvider auseinandersetzen und Dir Extension-Methoden genauer anschauen. Wie schon geschrieben ist das erstellen je einer eigenen Klasse je Control nicht de sinnvollste Weg solche Dinge umzusetzen.
Da hat Abt recht - meine Erfahrungen stammen noch aus 2019 (da hab ich das zum letzten mal selbst genutzt). Da war es noch möglich ohne ein Zertifikat zu veröffentlichen und die Anwendung wurde vom Microsoft selbst signiert. Seit Mai 2023 ist das wohl anders. Das hier habe ich dazu gefunden:
On June 16, 2022 we announced an update to Store policy. Win32 apps are required to be digitally signed, with a code signing certificate that chains up to a certificate issued by a Certificate Authority (CA) that is part of the Microsoft Trusted Root Program. New app submissions will not be allowed without an appropriate signature after May 1, 2023. Existing apps must be updated to include a digital signature per this policy before January 15, 2024.
Previously, all Microsoft Store apps (native UWPs for example) were hosted and signed by the Microsoft Store and received a Microsoft signature. With the change to our policy enabling Win32 apps to be listed in the Microsoft Store, and the removal of the waitlist for submitting Win32s, the new policy requires those apps to be digitally signed, and ensures all apps that customers acquire and download from the Microsoft Store have a trusted digital certificate.
Als Alternative zur Zertifizierung könntest Du Deine Anwendung auch im Windows-AppStore anbieten und dann von Deiner Website auf den Eintrag im Store verlinken. Damit entfällt für dich die Notwendigkeit, das Installationsprogramm selbst signieren zu müssen...
Veröffentlichen von Windows-Apps - Windows apps | Microsoft Learn
Wie kommst Du darauf, dass sich für einen Public Folder 'DefaultItemType' ändert, nur weil Du für den Ordner 'E-Mail-aktivierst'?
Die 'E-Mail-Aktivierung bedeutet doch IMHO nur, dass der Ordner unter eigener E-Mail-Adresse erreichbar ist und ggf. als Absender verwendet werden kann.
Ich verstehe nicht, warum Outlook den Ordner falsch behandelt (ich kann nur Postings erstellen und keine Mails verschicken).
Ich verstehe nicht ganz, was Du hier versuchst. Natürlich kannst Du im Ordner nur 'Postings' erstellen. Der Ordner selbst ist ja kein Postfach, was tatsächlich E-Mails verschicken kann. Du kannst nur aus deinem Postfach heraus E-Mails im Namen des Ordners verschicken - der Empfänger sieht dann den Ordner als 'Absender' und Antworten gehen in diesen Ordner.
BTW: Ich würde für solche Dinge immer nur EWS verwenden. Man tut sich deutlich leichter, hat mehr Möglichkeiten und ist nicht auf ein installiertes Outlook angewiesen.
Wenn Du, wie von mir empfohlen einen BreakPoint in fNummerComboBox_SelectedIndexChanged und einen in Vertrageinzel_Load setzt, wirst Du bemerken, dass fNummerComboBox_SelectedIndexChanged VOR Vertrageinzel_Load ausgeführt wird. Das heisst, Deine fNummerComboBox löst das Ereignis SelectedIndexChanged bereits aus, bevor dein Form das OnLoad-Ereignis auslöst und damit Vertrageinzel_Load ausführt.
Das liegt daran, dass Du höchstwahrscheinlich bereits im Designer für fNummerComboBox einen Wert setzt. Das setzen dieses Wertes wiederum führt dazu, dass fNummerComboBox_SelectedIndexChanged aufgerufen wird.
Der Ablauf ist also so:
Du siehts also, dass Du das SelectedIndexChanged-Ereignis bis NACH der Ausführung von Vertrageinzel_Load ignorieren musst.
Hier findest Du noch ein paar Informationen zur Reihenfolge der ausgelösten Events:
Reihenfolge der Ereignisse - Windows Forms .NET Framework | Microsoft Learn
Leider ist im gezeigten Code nicht ersichtlich, wo genau 'PreisBerechnen' aufgerufen wird und was genau 'GetPreisProTag' macht. Ohne die Information wird Dir niemand helfen können.
Ansonsten: Nutze den Debugger um Schritt für Schritt den Code durchzugehen. Dann wirst Du schon sehen, dass Du 'PreisBerechnen' offenbar aufrufst, bevor die Tabelle gefüllt wird. Kleiner Hinweis: fNummerComboBox_SelectedIndexChanged ist der Punkt, an dem Du das Debuggen beginnen solltest...
In der aktuellen Version von C# (12.0) kann man das z.B. so machen:
enum DX
{
DXLOCK,
HIGHDEF,
SCHNECKEN_POWER
}
// primärerer Constructor: https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/primary-constructors
class RegisterEigenschaften(byte val,byte iFlag, string nameStr,DX regNr)
{ }
class DFx
{
// collection expression: https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-12#collection-expressions
List<RegisterEigenschaften> DFlist= [
new(0,0,"Status", DX.DXLOCK ),
new(0,0,"AnalogValue", DX.HIGHDEF),
new(0,0,"PWM", DX.SCHNECKEN_POWER),
];
}
Für Desktop-Anwendungen gibt es außerhalb der Microsoft-Welt auch noch dies hier:
Noch Beta, sieht aber schon recht vielversprechend aus...
Wenn es auch was kosten darf... Schaust Du hier: MVVM Framework for WinForms (devexpress.com)
Nachdem Du ja nun schon weißt, was und warum alles nicht geht und hier mal bisschen was konstruktiveres... Bitte beachten, dass es durchaus Einschränkungen für die Funktion dieses Codes geben kann (virtuelle PCs etc.) - inwieweit das für dich nutzbar ist, musst Du selbst entscheiden - hängt auch davon ab, ob und wie Du die 'Umgebung' in der das genutzt werden soll unter 'Kontrolle' hast.
Wie kann ich per C# einen Rechner eindeutig identifizieren?
using System.Management;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
namespace SystemInfo;
[SupportedOSPlatform("windows")]
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
SystemInfo ifo = new();
Console.WriteLine("CPU: "+ifo.IDCpu);
Console.WriteLine("MB: "+ifo.IDMotherboard);
Console.WriteLine("MAC: "+ifo.IDMac);
Console.WriteLine("DRIVE: "+ifo.IDSystemDrive);
Console.WriteLine(ifo.UniqueID);
Console.Read();
}
}
/// <summary>
/// Informationen zum Computer, auf dem die Anwendung gerade ausgeführt wird.
/// </summary>
public class SystemInfo
{
private string? _cpuid = null;
private string? _macid = null;
private string? _mbid = null;
private string? _systemserial = null;
private string? _uniqueid = null;
/// <summary>
/// ID des Prozessors des PCs
/// </summary>
[SupportedOSPlatform("windows")]
public string IDCpu
{
get
{
if (_cpuid != null) return _cpuid;
using ManagementClass mc = new("Win32_Processor");
using ManagementObjectCollection moc = mc.GetInstances();
foreach (var mo in moc)
{
_cpuid = mo.Properties["ProcessorId"].Value.ToString();
break;
}
_cpuid ??= "";
return _cpuid;
}
}
/// <summary>
/// ID des Motherboards des PCs
/// </summary>
[SupportedOSPlatform("windows")]
public string IDMotherboard
{
get
{
if (_mbid != null) return _mbid;
using ManagementClass mc = new("Win32_BaseBoard");
using ManagementObjectCollection moc = mc.GetInstances();
foreach (var mo in moc)
{
_mbid = mo.Properties["SerialNumber"].Value.ToString();
break;
}
_mbid ??= "";
return _mbid;
}
}
/// <summary>
/// MAC-Adresse der ersten Netzwerkkarte/der ersten Netzwerkschnittstelle des PCs
/// </summary>
public string IDMac
{
get
{
if (_macid != null) return _macid;
NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface ni in interfaces)
{
if (ni.Supports(NetworkInterfaceComponent.IPv4) == false &&
ni.Supports(NetworkInterfaceComponent.IPv6) == false)
continue;
PhysicalAddress pa = ni.GetPhysicalAddress();
_macid = pa.ToString();
break;
}
_macid ??= "";
return _macid;
}
}
/// <summary>
/// Volume-ID des Systemlaufwerks
///
/// Seriennummer des Laufwerkes, auf dem sich das Betriebssystem befindet.
/// </summary>
public string IDSystemDrive
{
get
{
if (_systemserial != null) return _systemserial;
_systemserial = VolumeSerial(new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.System)));
return _systemserial;
}
}
/// <summary>
/// Liefert die VolumeInformationen zu einem Laufwerk
/// </summary>
/// <param name="PathName">Name des Pfades/Laufwerks</param>
/// <param name="VolumeNameBuffer"></param>
/// <param name="VolumeNameSize"></param>
/// <param name="VolumeSerialNumber"></param>
/// <param name="MaximumComponentLength"></param>
/// <param name="FileSystemFlags"></param>
/// <param name="FileSystemNameBuffer"></param>
/// <param name="FileSystemNameSize"></param>
/// <returns></returns>
[DllImport("kernel32.dll")]
public static extern long GetVolumeInformation(string PathName, StringBuilder VolumeNameBuffer, uint VolumeNameSize, ref uint VolumeSerialNumber, ref uint MaximumComponentLength, ref uint FileSystemFlags, StringBuilder FileSystemNameBuffer, uint FileSystemNameSize);
/// <summary>
/// Ermittelt die Seriennummer eines Laufwerkes als Hex-String
/// </summary>
/// <param name="dir">DirectoryInfo dessen VolumeSerial ermittelt werden soll</param>
/// <returns>Seriennummer als Hex-String (0x wenn ein Fehler auftrat)</returns>
public static string VolumeSerial(DirectoryInfo dir)
{
uint serNum = 0;
uint maxCompLen = 0;
string ret = "";
if (dir.FullName.Substring(1, 1) == ":")
{
StringBuilder VolLabel = new(256); // Label
uint VolFlags = new();
StringBuilder FSName = new(256); // File System Name
string drive = dir.FullName.Substring(0, 1) + ":\\";
GetVolumeInformation(drive, VolLabel, (uint)VolLabel.Capacity, ref serNum, ref maxCompLen, ref VolFlags, FSName, (uint)FSName.Capacity);
ret = Convert.ToString(serNum, 16);
}
else
{
throw new InvalidDataException($"{dir.FullName} is not located on a physical drive.");
}
return ret;
}
/// <summary>
/// eindeutige ID des Computers
///
/// Die eindeutige ID wird aus der ID der CPU,
/// der ID der Motherboards und der MAC-Adresse,
/// auf dem sich das Betriebssystem befindet gebildet
/// und dann verschlüsselt. Der so erstellte HashCode kann als eindeutige
/// ID des PCs verwendet.
///
/// Diese ID kann sich ändern, wenn das MotherBoard, die CPU, die Festplatte oder die Netzwerkkarte getauscht werden.
/// </summary>
[SupportedOSPlatform("windows")]
public string UniqueID
{
get
{
if (_uniqueid != null) return _uniqueid;
string ID = IDCpu + IDMac + IDMotherboard + IDSystemDrive;
using HMACSHA1 hmac = new();
hmac.Key = Encoding.ASCII.GetBytes(IDMotherboard);
hmac.ComputeHash(Encoding.ASCII.GetBytes(ID));
// Hash zu Hex-String konvertieren
StringBuilder sb = new();
foreach (var bt in hmac.Hash!)
sb.Append(bt.ToString("X2"));
_uniqueid = sb.ToString();
return _uniqueid;
}
}
}
Wenn es denn erstmal unbedingt kostenlos sein soll hilft dir das hier sicher weiter:
https://openbook.rheinwerk-verlag.de/visual_csharp_2012/
Zwar kein Video und nicht mehr ganz aktuell, aber für den Einstieg definitiv vollkommen ausreichend.
Kann mir jemand gute Anleitungen nennen (videoreihen auf Youtube) mit dem man etwas die Grundlagen lernen kann (in deutscher Sprache wäre super)
Statt auf Youtube kannst Du dich ja mal auf Udemy umschauen (z.B. hier: https://www.udemy.com/course/csharp-grundlagenkurs-fuer-anfaenger/).
Kann mir jemand sagen ob ich mit c# ein quiz bauen kann bei dem die fragen aus einer liste in zufällige reihenfolge ausgeben werden und die antworten ebenfalls?
Natürlich geht das - ich arbeite jetzt seit ca. 20 Jahren mit C# - da ist mir noch (fast) nix untergekommen, was mit C# nicht umsetzbar gewesen wäre... 😉
Wie Abt schon schrieb, vermute ich auch einen falschen Umgang mit unmanaged ressources (Bitmaps, Fonts, Pen - allgemein alles, was mit GDI zu tun hat führt gern zum beschriebenen Problem). Das führt dann dazu, dass die Anwendung irgendwann z.B. keine GDI-Handles mehr zur Verfügung hat.
Lade Dir mal den Process-Explorer aus den PSTools herunter und beobachte, ob bestimmte Speicher, Handles etc. sich permanent erhöhen.
Generell solltest Du auch mal überlegen, ob eine WinForms Anwendung das richtige Mittel ist, wenn das tagelang laufen soll. Eventuell kommst Du ja mit einem Dienst besser zurecht. Um ein zuverlässiges laufen zu garantieren sollte auch immer eine 'Überwachungsinstanz' prüfen, ob die Anwendung/der Dienst noch läuft und ggf. dafür sorgen, dass das wieder der Fall ist (man spricht hier oft von 'Watchdogs').
Neben den bereits schon angesprochenen Indizes, würde ich mich für Variante 2 entscheiden, diese aber wie folgt anpassen (damit keine Codeanpassungen notwendig sind):
SELECT
a.Id,
CASE WHEN b.Id IS NULL THEN a.Nr ELSE b.Nr END as Nr,
CASE WHEN b.Id IS NULL THEN a.Field1 ELSE b.Field1 END as Field1,
...
FROM Table1 AS a
LEFT JOIN Table2Edit AS b ON a.Id=b.Id
Du brauchst die Tabelle 2 nicht anfassen (keine Suffixe) und der lesende Code muss ebenfalls nicht angepasst werden. Hast Du hier Indizes für a.Id und b.IdEdit, ist diese Variante recht fix...
Lass mal gut sein - der TO wollte wissen, wie er Email's verschlüsseln kann. Da er sich nicht mehr gemeldet hat, scheint das ja geklärt - der Rest ist Zeitverschwendung. Ich bin jedenfalls raus...
Hilft Dir das hier vielleicht weiter?
Schön, dass Ihr Euren Public Key auf Eurer Website veröffentlicht... inwiefern soll Dir das nützen beim Mailversand AN den Kunden? 😉
Das hab ich doch gar nicht geschrieben - meine Aussage bezieht sich auf den Sachverhalt, dass 'ID's' ausgetauscht werden müssen und dies als eine Art Hindernis dargestellt wird - ich wollte damit lediglich aufzeigen, dass dieser Prozess kaum eine ernsthafte Hürde sein kann...
Und zum Rest: Ich wollte lediglich darstellen, dass Abt IMHO viel zu stark pauschalisiert in seiner Aussage und dass es durchaus Branchen gibt, wo die Verschlüsselung der Kommunikation zwischen den Geschäftspartnern usus ist. Das von Dir angesprochene 'Schlüsselmanagement' ist letztendlich - was den Aufwand angeht - auch eine Frage der Routine und der eingesetzten Lösungen (bei uns zum Beispiel wird dafür nicht Outlook o.ä. eingesetzt, sondern eine spezielle Lösung die eben die Verwaltung der Schlüssel und den Prozess an sich stark vereinfacht).
Es ist aber müssig das hier zu diskutieren, weil es letztendlich immer von den Geschäftsfeldern und betrieblichen Abforderungen abhängt. Sensible Dinge per Briefpost zu verschicken ist nicht in jedem Fall möglich 😉
Ich kenne ehrlich gesagt nicht ein Unternehmen, das so verschlüsselte Mails an Kunden verschickt.
Es macht im Kundenkontakt auch keinen Sinn, weil man erst mal die IDs austauschen muss - und das passiert im realen Leben so gut wie nie.
Naja, nur weil Du das nicht kennst, bedeutet das nicht, dass sowas nicht stattfindet - im Unternehmen, für das ich tätig bin ist das alltägliche Praxis. Man tauscht ja auch in der Regel keine 'IDs' aus, sondern stellt dem Kommunikationspartner seinen public key zur Verfügung (bei uns gibt es den als Download auf unserer Website).
Normalerweise verschickt man eben aus diesen Gründen gar keine Passwörter, sondern der Kunde setzt sie auf der Seite direkt. ...
Keine Ahnung, wie Du jetzt auf Passwörter kommst - darum geht es doch hier überhaupt nicht...
@Brendan
Falls Du es noch nicht getan hast, würde ich mir an Deiner Stelle mal GPG4Win (https://www.gpg4win.de/) herunterladen und das ganze mit den Kunden mal ein bischen durchspielen. Vielleicht reicht es ja auch aus, Anhänge zu verschlüsseln, statt der ganzen Email. Hier würde sich dann OpenPGP anbieten, da gibt es mit BouncyCastle (https://www.bouncycastle.org/) eine sehr gute Bibliothek...
Verwende App_Code oder noch besser - lagere den Code in eine eigene Klassenbibliothek aus. Was Dir zum Thema App_Code Ordner erzählt wurde macht IMHO in Verbindung mit WebForms keinen Sinn.
Dann nutze die TAG-Eigenschaft der Controls. Dort kannst Du ein Objekt einer Klasse ablegen, die Deine zusätzlichen Eigenschaftenn implementiert...
public class AdvControlProperties
{
public double Factor { get; set; }
public bool Selected { get; set; }
}
...
Control newControl = new Label() { Tag = new AdvControlProperties() };
Verstehe ich richtig, dass Dein Problem ist, dass Du nicht genau weißt, wie Du statt Deiner 'Control'-Klasse Labels etc. hinzufügst, weil Dir nicht klar ist, wie Du Deine zusätzlichen Properties in diese Label etc. bekommst?
Da gibt es mehrere Ansätze: du könntest Ableitungen der Standard-Controls (Label etc.) erstellen und diese abgeleiteten Klassen verwenden oder die Tag-Eigenschaft der Standardklassen für Deine zusätzlichen Informationen nutzen...
Falls es darum nicht geht, spezifiziere bitte 'finde das ganze sehr unschön'...
'glandorf' schrieb ja bereits, dass Du auf die Daten des GridViews jederzeit zugreifen kannst (DataGridView.Rows, DataGridView.Row.Cells etc.). Allerdings solltest Du Dir auch das CellPainting-Ereignis mal genauer anschauen...
Wenn schon von Outlook gesprochen wurde, ist ja vielleicht auch die Nutzung eines ggf. schon vorhandenen Exchange-Servers eine Option. Ich habe sehr gute Erfahrungen mit der EWS Managed API von Exchange gemacht: https://msdn.microsoft.com/en-us/library/office/dd633710(v=exchg.80).aspx
Wie genau 'formatierst' Du denn die angezeigten Daten (Code)?
Für jede Sprache eine Spalte z.B.. Da sind Deiner Phantasie keine Grenzen gesetzt....
Ich kann Taipi88 hier nur beipflichten. Ich entwickle selbst eine sehr komplexe Anwendung, in der WaWi nur einen Teil ausmacht und verwende dafür ein TabbedUI auf Basis der DevExpress-Controls (https://www.devexpress.com/Products/NET/Controls/WinForms/Desktop_UI/). Für die Anwender ist es einfach ein Segen, wenn Sie z.B. mehrere Kunden, Belege oder Produkte parallel öffnen und vernünftig anordnen und verwalten können. Das können dann gern auch schon mal 40 - 50 'Fenster' sein, die da 'gleichzeitig' geöffnet sind...
Verschweigen darf man aber nicht, dass das Ganze schon einen gewissen Mehraufwand bedeutet, weil z.B. Daten zwischen den Fenstern ggf. synchronisiert werden müssen - hier muss man sich im Vorfeld Gedanken machen und sich eine vernünftige Basis schaffen - dann ist es allerdings IMHO sehr sehr benutzerfreundlich - gerade wenn man mehrere Monitore zur Verfügung hat...
Also in Zeiten von immer mehr 'Multi-Monitor'-Umgebungen sind MDI-Anwendungen wirklich überlebt und in meinen Augen - wurde ja schon mehrfach erwähnt - auch eine unnötige Gängelung der User. Ich sehe auch gar keinen Grund warum sich alle Fenster der Anwendung ebenfalls minimieren müssen, wenn ich das Hauptfenster minimiere - das überlasse ich dem Anwender. Aber wenn Du das unbedingt benötigst, hilft Dir z.B. die Auflistung Form.OwnedForms weiter. Über die kannst Du dann z.B. alle 'OnwnedForms' ebenfalls minimieren, wenn das Hauptfenster minimiert wird und ähnliches...
Alternativ dazu kannst Du mal nach dem Stichwort 'Docking' suchen... Es gibt zu diesem Thema zahlreiche Frameworks (DevComponents, DevExpress etc...).
Und wenn es denn MDI sein soll: bei DevExpress gibts eine Lösung, bei der die Skins der Kindfenster dem Elternfenster entsprechen (bzw. frei wählbar sind).
Um das 'Form' zu finden, in dem ein Control dargestellt wird, eignet sich die Methode FindForm() (siehe https://msdn.microsoft.com/de-de/library/system.windows.forms.control.findform(v=vs.110).aspx) des Controls deutlich besser als Parent, weil Parent - wie p!llie schon schrieb - nicht zwangsweise das Form sein muss, sondern ein beliebiger Controlcontainer sein kann.
Die Datenquelle kommt zustande, indem der zuvor erstellte Report dem ReportViewer zugewiesen wird (in dem kleinen Popup mit der Überschrift Report Tasks - zu erreichen über einen Klick auf den kleinen Pfeil rechts oben am ReportViewer-Control). Und das hat bei Dir nicht geklappt?
Ich weiß ja nicht wonach Du schon gesucht hast, aber es gibt Unmengen von Kombinationen aus Tree- und GridViews im Netz...
https://www.codeproject.com/Articles/23746/TreeView-with-Columns
https://sourceforge.net/projects/treeviewadv/
https://www.codeproject.com/Articles/3273/ContainerListView-and-TreeListView-Writing-VS-NET
https://blogs.msdn.microsoft.com/markrideout/2006/01/08/customizing-the-datagridview-to-support-expandingcollapsing-ala-treegridview/
...
> 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?
Der letzte Parameter von DrawString ist ein Rectangle, dass den Bereich beschreibt, in dem gezeichnet wird. Diesen Bereich musst Du in der Schleife berechnen...
Projekteigenschaften -> Debuggen -> Befehlszeilenargumente.
Noch ein Hinweis zum Zeichnen: du zeichnest innerhalb der Schleifen immer an die gleiche Stelle. Du musst zum Zeichnen des Labyrinths natürlich die Koordinaten an denen das Zeichen gezeichnet wird anpassen.
Du musst Deiner MyForm-Klasse in irgendeiner Form das Array übergeben. Deine Main-Methode hat da wo sie jetzt steht nichts zu suchen, die gehört in eine separate Klasse (i.d.R. Program(.cs)). Ausserdem fehlt in Deinem Code der NameSpace.
using System;
namespace MeineApp
{
public static class Program
{
public static void Main(string[] args)
{
int spalten, zeilen;
spalten = Int32.Parse(Console.ReadLine());
zeilen = Int32.Parse(Console.ReadLine());
char[,] labyrinth = new char[zeilen, spalten];
for (int i = 0; i < zeilen; i++)
{
for (int j = 0; j < spalten; j++)
{
labyrinth[i, j] = (char)Console.Read();
Console.Write(labyrinth[i, j]);
}
}
Application.Run(new MyForm() { Labyrinth = labyrinth });
}
}
}
using System.Windows.Forms;
using System.Drawing;
namespace MeineApp
{
public class MyForm : Form
{
public MyForm()
{
Text = "Labyrinth";
}
public char[] Labyrinth { get; set; }
protected override void OnPaint(PaintEventArgs e)
{
// hier mit Deinen zwei for-Schleifen das zeichnen implementieren
for (int i = 0; i < Labyrinth.GetLength(0); i++)
{
for (int j = 0; j < Labyrinth.GetLength(1); j++)
{
// das eigentliche zeichnen...
}
}
//e.Graphics.DrawString("inhalt vom array soll gezeichnet werden", Font,
// new SolidBrush(Color.Black), ClientRectangle);
}
}
}
Ohne zu wissen, was und wie diese 'ServerAnwendung' genau macht, wird Dir hier wahrscheinlich keiner diese Fragen beantworten können.
Nur mal ganz grundsätzlich:
Ist die 'ServerAnwendung' ein Dienst? Wenn ja, kannst Du dort schon einiges einstellen, was passieren soll, wenn der Dienst 'abstürzt'. Ausserdem böte sich die Verwendung eines sog. WatchDogs an - ein zweiter Dienst, der nur nachschaut ob der erste bereits läuft und wenn nicht diesen startet. In einer perfekten Welt würde Dein ServerDienst dann auch noch den Watchdog überwachen, so dass beide sich gegenseitig ständig 'im Auge' haben...
Ist Deine ServerAnwendung kein Dienst, solltest Du das so handhaben, dass die Anwendung nur gestartet wird, wenn das abarbeiten notwendig ist - also starten, Aufgaben erledigen und danach wieder beenden. Müssen die Aufgaben regelmässig erledigt werden, kannst Du die ANwendung als geplanten Task starten (mit den Bordmitteln von Windows).
Dein Code ist ziemlich wirr.
Wie kommt InitializeComponent() in die Methode ShowLineJoin - normalerweise wird diese im Constructor des Fensters aufgerufen?
Wo/wie wird ShowLineJoin aufgerufen?
Prinzipiell: Du musst Die Methode OnPaint überschreiben und/oder Dich an den Paint-Event des Fensters halten.
Um vielleicht auch mal eine sinnvolle Antwort zu liefern: Wenn Du den Button erst umbenennst und DANACH die Click-Methode generierst bekommt diese auch den passenden Namen. Ansonsten vllt. noch das Stichwort 'Refactoring' - wenn Du die Methode umbenennst wird der Name - wenn Du alles richtig machst - auch in der *.designer.cs angepasst...
@Abt: Was Du da schreibts ist ein Witz oder...
was ich nicht hinbekomm ist: das man nur den gedrehten text sieht
Im überschriebenen OnPaint wird am Ende base.OnPaint aufgerufen. Damit wird die Standardzeichenroutine nach der Anzeige Deines eigenen Textes aufgerufen. Das ist falsch...
geschweige denn das sich bei 90 oder 270 ° die größe des Labels anpasst
Das geschieht nicht automatisch, dass musst Du selbst umsetzen... (Stichwort: MeasureString)
Ich komm noch mal kurz zum Ausgangspunkt zurück. Hier meine Lösung zum Aufruf generischer Methoden mittels Type. Ich habe den Ursprungscode verwendet, DeineKlasse meint die Klasse, die GetWert enthält (im Beispielcode ja die gleiche, die ebenfalls Do enthält).
public string Do(Type t)
{
var methodinfo = typeof(DeineKlasse).GetMethod(nameof(DeineKlasse.GetWert));
var methodref = methodinfo.MakeGenericMethod(t);
dynamic wert = methodref.Invoke(this, null);
return wert.ToString();
}
Edit: Oh grad gesehen, das SirRufo eine Lösung mittels MakeGeneric bereits verlinkt hat - naja, spart sich ggf. eben einer das klicken auf den Link 😉
Du solltest Dir mal ein paar UI-Bibliotheken für HTML anschauen. Container mit wechselnden Inhalten sind damit meist sehr leicht umsetzbar.
Anbieten würden sich z.B. Frameworks wie:
Bootstrap
https://v4-alpha.getbootstrap.com/
MetroUI
https://metroui.org.ua/
React
https://facebook.github.io/react/
Angular
https://angular.io/
usw...
Der Vollständigkeit halber vllt. noch:
https://www.devexpress.com/Products/NET/Controls/WinForms/Scheduler/
https://www.infragistics.com/products/windows-forms/scheduling/schedule
http://www.devcomponents.com/dotnetbar/ScheduleCalendarControl.aspx
Persönlich bevorzuge ich DevExpress...
Zum Thema Lokalisierung bei Telerik:
http://docs.telerik.com/devtools/winforms/scheduler/localization/translating-strings
Könnte aber gut sein, dass die bereits Übersetzungen für andere Sprachen mitliefern. Bei DevExpress ist das jedenfalls der Fall...
@C4RLO, ob die UX für Dich passt: probiers doch einfach mal aus?!
Ehrlich gesagt kann ich sowas wie ein UI - abgesehen von der Commandozeile nicht finden. Kann sein, dass das Ergebnis besser/vergleichbar ist als/mit SharpDox und das sich das Ganze besser in VS integrieren lässt, aber da ich SharpDox nicht täglich brauche ziehe ich dessen verständliche UI DEUTLICH diesem docFX vor. Mit dem Ergebnis von SharpDox kann ich für meinen Bedarf sehr sehr gut leben und eine tiefere Integration in VS brauche ich nicht unbedingt...
Also ja, ich würde es begrüßen, wenn SharpDox am Leben erhalten wird... Viele Dank an Gaez, für dieses wirklich sehr hilfreiche udn nützliche Tool (kann man gar nicht oft genug sagen)!
Da die .NET-Runtime unter anderem auch den C# Compiler enthält, kannst Du Deine 'Scripte' auch komplett in C# schreiben. Schau Dir hierzu mal die Klasse CodeDomProvider und da insbesondere die Methode CompileAssemblyFromSource an...
Das hört sich alles nach einem ziemlichen Gemurkse an. Warum nicht ganz klassisch eine vernünftige Datenbank, auf die die Clients zugreifen?
Übergeben wird ein Array. Die Methode manipuliert die Werte in diesem Array.
Es gibt in C# Objekte, die 'per value' (dazu zählen Objekte von Klassen wie int, string etc. - mehr dazu findest Du hier C# - Data Types) und Objekte die 'per reference' übergeben werden (Objekte aller anderen Klassen wie eben auch Arrays).
Was Du suchst, nennt sich 'visual inheritance' - hier findest Du mehr zum Thema:
MSDN: Windows Forms Visual Inheritance
Zeig doch mal etwas mehr von Deinem Code und beschreibe vor allem genauer, was Du erreichen möchtest. Mir scheint als gäbe es da ein grundlegenderes Verständnisproblem...
Wenn Sie Arbeitsplatzrechner und SQL-Server im selben Netz befinden, kann Dir wohl nur der Admin des Netzwerkes weiterhelfen. Vielleicht ist ja auch einfach der SQL-Server zu bestimmten Zeiten nicht oder eben nur schwer erreichbar (Datensicherung etc.).
Da kann man nicht viel machen, außer das Fenster im Designer eben etwas größer zu gestalten... Sicher kannst Du hier und da auch einige der Fensterschaltflächen 'weglassen' - ist der Dialog/das fenster nicht vergrößerbar, macht i.d.R. auch die 'Maximieren'-Schaltfläche keinen Sinn.
Wie genau verbindest Du denn Deinen Laptop mit dem Internet, bevor Du die VPN Verbindung herstellst? Ich vermute am ehesten Probleme mit der Internetverbindung (schlechte Qualität, langsam etc.).