Ergänzung: Wenn ich alle Spalteneiner Row ändere, funktioniert es. Angemeckert werden die nicht editierten Spalten.
Für den dynamischen Inhalt eines Datagrid habe ich eine ValidationRule geschrieben:
public override ValidationResult Validate(object value,
System.Globalization.CultureInfo cultureInfo)
{
var bg = (BindingGroup)value;
DataRowView rView = bg.Items[0] as DataRowView;
if (Columns != null)
{
bool result = true;
foreach (string name in Columns.Keys)
{
object iValue = DBNull.Value;
if (result)
{
bool isDirty = bg.IsDirty;
bool isSealed = bg.IsSealed;
result = bg.TryGetValue(rView, name, out iValue);
}
if (!result)
return new ValidationResult(false, $"Propertie \"{Columns[name].ColumnHeader}\" not found!");
else if (iValue == DBNull.Value)
return new ValidationResult(false, $"\"{Columns[name].ColumnHeader}\" is necessary!");
else
{
switch (Columns[name].DataType)
{
case ApClasses.EnumDataType.NVarChar100:
case ApClasses.EnumDataType.Bit:
if (iValue.ToString().Trim().Length == 0)
return new ValidationResult(false, $"\"{Columns[name].ColumnHeader}\" should be at least 1 char!");
break;
case ApClasses.EnumDataType.BigInt:
case ApClasses.EnumDataType.Int:
if (!ApClasses.ApUtilities.ConvToInt(iValue).ToString().Equals(iValue.ToString()))
return new ValidationResult(false, $"\"{Columns[name].ColumnHeader}\" should be an integer!");
break;
case ApClasses.EnumDataType.Float:
if (!ApClasses.ApUtilities.ConvToFloat(iValue).ToString().Equals(iValue.ToString()))
return new ValidationResult(false, $"\"{Columns[name].ColumnHeader}\" should be an float!");
break;
case ApClasses.EnumDataType.DateTime2:
if (!ApClasses.ApUtilities.ConvToDate(iValue).ToString().Equals(iValue.ToString()))
return new ValidationResult(false, $"\"{Columns[name].ColumnHeader}\" should be an TimeStamp!");
break;
}
}
}
}
return ValidationResult.ValidResult;
}
}
Diese funktioniert im Prinzip. Jedoch bekomme ich sporadisch falsche Validierungsergebnisse. "bg.TryGetValue(rView, name, out iValue);" liefert false, obwohl im DataRowView der name="ValueIn01" enthalten ist. Hier ist die exportierte DataRowView.
ID;ID_Equipments;ID_Parameterization;ValueIn00;ValueIn01
18;1;1;38000;4
Das Dictionary<string, ApValueMapping> Columns ist immer korrekt gefüllt. Hier zm besseren Verständnis noch das ApValueMapping:
public class ApValueMapping
{
public string? ColumnHeader { get; set; }
public EnumDataType DataType { get; set; }
public ApValueMapping(string columnHeader, EnumDataType dataType)
{
ColumnHeader = columnHeader;
DataType = dataType;
}
}
Gibt es bei Euch schon Erfahrungen in dieser Richtung?
Hallo Th69, ich bin auf den Weg in den Ski-Urlaub. Sobald ich wieder da bin, versuche ich eine Refernz von "CurrentNodeName" an die child-nodes zu übergeben. Ich danke Dir für die Anregung.
Hallo Th69, danke für Deine Mühe und die schnelle Antwort. Mein Problem ist die Kaskadierung. Events, welche ich versuchte funktionierten nur in der ersten parent-ebene. Also zwischen "node" und den ersten children. Ich habe zwar etwas von blubbernden Events gelesen, denke aber, dies bezieht sich nur auf GUI-Container.
Ich arbeite mich gerade in die wpf-Technologie ein. Die größten Probleme habe ich mit dem Verständnis des Bindings. Ich möchte Inhalte des selektierten Node ausserhalb eines TreeViews nutzen. Um dies zu testen habe ich Cavemans (ich danke Dir) Beispiel angepasst und eine TextBox mit dem CurrentNodeName gebunden:
XAML:
<Window x:Class="ApTest.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:sys="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:ApTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
<Window.Resources>
<local:MultiToBrushConverter x:Key="conv"/>
<ObjectDataProvider x:Key="drives"
ObjectType="{x:Type sys:Environment}"
MethodName="GetLogicalDrives"/>
</Window.Resources>
<Grid>
<StackPanel>
<TextBox Text="{Binding CurrentNodeName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged }"/>
<TreeView Name="myTreeView" Grid.Row="0" ItemsSource="{Binding Nodes}">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<Setter Property="FontWeight" Value="Normal" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="ExtraBold" />
</Trigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</StackPanel>
</Grid>
</Window>
MainWindowViewModel:
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Text;
using System.Threading.Tasks;
namespace ApTest
{
internal class MainWindowViewModel : Node
{
public ObservableCollection<Node> Nodes { get; set; }
internal MainWindowViewModel()
{
Nodes = new ObservableCollection<Node>
{
new Node() { Name = "Node 01" },
new Node() { Name = "Node 02" },
new Node() { Name = "Node 03" },
new Node() { Name = "Node 04" },
new Node() { Name = "Node 05" },
new Node() { Name = "Node 06" }
};
Nodes[1].Children.Add(new Node() { Name = "Node 02.1" });
CurrentNodeName = "not assigned";
}
}
}
Node:
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace ApTest
{
public class Node : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private string currentNodeName;
public string CurrentNodeName
{
get { return currentNodeName; }
set {
currentNodeName = value;
OnPropertyChanged(nameof(CurrentNodeName));
}
}
public string Name { get; set; }
public ObservableCollection<Node> Children { get; set; }
public Node()
{
Children = new ObservableCollection<Node>();
}
bool isSelected;
public bool IsSelected { get => isSelected;
set
{
isSelected = value;
if (isSelected)
CurrentNodeName = Name;
}
}
}
}
Ich verstehe nicht, warum für "CurrentNodeName" nur die Initialisierung "not assigned" angezeigt wird. In der Klasse Node wird "CurrentNodeName" gesetzt. OnPropertyChanged wird aufgerufen. Der aktuelle Wert wird aber nicht abgeholt. Kann mir jemand helfen?
Hallo,
manchmal hilft der Zufall. Wenn es passiert melde ich mich.
Danke
Das Ausschliessen exklusiver Projekte hat nichts gebracht. Im Anschluss habe ich den versteckten Ordner ".vs" gelöscht: keine Änderung. Da ich zu faul war die verbleibenden Projekte einzeln zu entfernen, habe ich die Solution gesichert, neu angelegt und die Projekte einzeln hinzu gefügt. Ich habe die Solution jedes mal gespeichert, entladen und neu geladen. Es war mühsam, hat sich aber gelohnt. Beide Projektmappen enthalten nun exakt die gleich Anzahl Projekte. Die neue Projektmappe wird schnell, die alte mit der 4 Minuten-Pause geladen.
Beim Vergleich der beiden *.sln - Dateien habe ich nicht wirklich etwas gefunden. Einzig die Reihenfolge der Projekte und die UID des Solution sind unterschiedlich. Aus zeitgründen breche ich nun ab.
Hallo gfoidl, danke für die schnelle Antwort.
Ich muss meine Frage etwas korrigieren. Es handelt sich nicht um ein einziges Projekt, sonder um eine Projektmappe mit insgesamt 45 Projekten.
Die Anzahl der Erweiterungen ist sehr übersichtlich. Ich habe sie alle deaktiviert und konnte keinerlei Änderung nach dem Neustart von VS 2019 fest stellen.
Ich werde nun, hier exklusiv genutze, Projekte ausschließen.Vielleicht kann ich es eingrenzen. Ich melde mich wieder.
Bei einem einzige Projekt hängt VS 2019 mit der Meldung "Projektmappe wird vorbereitet..". Es wird keine Datei mit einer URL geöffnet! Hat jemand Erfahrung damit? Im ActivityLog findet sich nur folgender Eintrag:
<entry>
<record>675</record>
<time>2023/11/14 15:36:29.562</time>
<type>Information</type>
<source>MruList</source>
<description>Did not find item to promote</description>
</entry>
<entry>
<record>676</record>
<time>2023/11/14 15:40:15.102</time>
<type>Information</type>
<source>VisualStudio</source>
<description>Begin package load [ProviderPackage]</description>
<guid>{5F2E5E42-4192-4D79-A0D8-1D881E808829}</guid>
</entry>
Hallo Th69,
danke für die Antwort. Anchor funktioniert in der Basis-Klasse und in den abgeleiteten Klassen.
Ändert man die Größe der abgeleiteten Klasse verschiebt sich der neu hinzugefügte Button sogar außerhalb der GroupBox
(welche hier verkleinert wurde). Ich vermute Microsoft hat hier noch Optimierungsbedarf. Kennt man das aktuelle
Verhalten, kann man ja darauf achten.
Danke für die schnelle Antwort. Den neuen Button habe ich inzwischen gefunden. Er lag außerhalb des Formats mit exakt den gleichen Koordinaten wie in der Basisklasse.
Alle Button sind an "Bottom, Right" gebunden. Während der Erstellung der Klasse "DruckArtikel" wurde die Form verkleinert.
Gibt es eine Trick die neuen Controls im Formular zu halten?
Im Voraus ein großer Dank, für die Zeit die Ihr für mich opfert.
Ich habe eine Windows.Forms Basisklasse "DruckStammdaten" geschrieben. Diese enthielt bis heute 2 Buttons [ Druck ] und [ Abbruch ].
Die Klasse "DruckArtikel" erbt von "DruckStammdaten" und alle funktionierte super.
Nun möchte ich gerne zusätzlich die aufbereiteten Daten exportieren und habe einen neuen Button [ Export ] in der Basisklasse eingefügt.
Ich habe die Basisklasse neu übersetzt und "DruckArtikel" komplett geschlossen und wieder geöffnet. Mein neuer Button wird ignoriert.
Erstelle ich eine neue Klasse, welche von "DruckStammdaten" erbt, ist der neue Button vorhanden.
Kann ich eine Aktualisierung erzwingen?
Hallo Th69,
vielen Dank. Nach dem ich festgestellt hatte, das
this.MouseRightButtonUp
genauso funktioniert wie
this.ContextMenu.MouseRightButtonUp
begann es zwischen den Ohren zu leuchten. Es durfte nicht
this.ContextMenu.ContextMenuOpening
(was sich ja auf das Kontextmenue des Kontextmenues bezieht)
sonder muss natürlich als
this.ContextMenuOpening
resgistriert werden.
Damit ist Alles gut und dieses Problem (3 Tage schäm) ist gelöst!
Ergänzung: Ich habe von "System.Windows.Controls.RichTextBox" aus der WPF und nicht aus
"System.Windows.Forms.RichTextBox" aus dem .NET Framework geerebt.
Ja, das war Absicht "ContextMenu.ContextMenuOpening" als Suchbegriff ergab genau 4 Antworten. Alle Probleme wurden in "GUI: WPF und XAML" behandelt. Ich vermute meinen Fehler bei der Realisierung ohne XAML. Das im Link genannte Beispiel wurde mit XAML erstellt. Ich suche die Ursache gerade in den "Routed Events". Diese gibt es auch nur in der WPF.
Es kann natürlich auch am Zusammenspiel dieser beiden Technologien liegen.
Ich möchte für die Rechtschreibkorrektur ein System.Windows.Controls.RichtextBox in Windows.Forms einbinden.
Um Schriften und Farben zu ändern habe ich in eine eigen Klasse von System.Windows.Controls.RichTextBox abgeleitet:
public partial class BOPLibFormsRichTextBox : System.Windows.Controls.RichTextBox
{
private System.Windows.Forms.FontDialog fD;
private System.Windows.Forms.ColorDialog cD;
private System.Windows.Forms.Form pF;
public BOPLibFormsRichTextBox() : base()
{
this.ContextMenu = new ContextMenu();// getContextMenu();
this.ContextMenu.ContextMenuOpening += ContextMenu_ContextMenuOpening;
}
private void ContextMenu_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
throw new NotImplementedException();
}
private ContextMenu getContextMenu()
{
ContextMenu result = new ContextMenu();
result.ContextMenuOpening += Result_ContextMenuOpening;
//Can create STATIC custom menu items if exists here...
MenuItem mi0 = new MenuItem(); mi0.Header = "Alles _Markieren"; mi0.Tag = 0; mi0.Click += mi_Click; result.Items.Add(mi0);
MenuItem mi1 = new MenuItem(); mi1.Header = "_Standardschrift"; mi1.Tag = 1; mi1.Click += mi_Click; result.Items.Add(mi1);
MenuItem mi2 = new MenuItem(); mi2.Header = "Schriftart _Wählen"; mi2.Tag = 2; mi2.Click += mi_Click; result.Items.Add(mi2);
MenuItem mi3 = new MenuItem(); mi3.Header = "_Farbe wählen"; mi3.Tag = 3; mi3.Click += mi_Click; result.Items.Add(mi3);
MenuItem mi4 = new MenuItem(); mi4.Header = "_Ausschneiden"; mi4.Tag = 4; mi4.Click += mi_Click; result.Items.Add(mi4);
MenuItem mi5 = new MenuItem(); mi5.Header = "_Kopieren"; mi5.Tag = 5; mi5.Click += mi_Click; result.Items.Add(mi5);
MenuItem mi6 = new MenuItem(); mi6.Header = "_Einfügen"; mi6.Tag = 6; mi6.Click += mi_Click; result.Items.Add(mi6);
MenuItem mi7 = new MenuItem(); mi7.Header = "_Löschen"; mi7.Tag = 7; mi7.Click += mi_Click; result.Items.Add(mi7);
MenuItem mi8 = new MenuItem(); mi8.Header = "S_uchen"; mi8.Tag = 8; mi8.Click += mi_Click; result.Items.Add(mi8);
return result;
}
private void mi_Click(object sender, RoutedEventArgs e)
{
throw new NotImplementedException();
}
}
Eingebunden ist diese Control wie folgt:
public partial class TestForm : Form
{
public TestForm()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
var host = new System.Windows.Forms.Integration.ElementHost();
host.Dock = DockStyle.None;
host.Location = new Point(20, 20);
host.Size = new Size(300, 60);
var rtb = new BORGAPAK.BOPLibFormsRichTextBox();
rtb.SpellCheck.IsEnabled = true;
host.Child = rtb;
this.Controls.Add(host);
rtb.Selection.Text = "Dies ist ein Test";
}
}
Die Click-Events für die Einträge in ContextMenu funktionieren. Das ContextMenuOpening-Event wird ignoriert.
Definiere ich kein eigenes ContextMenu funktioniert die Rechtschreibprüfung. Definiere ich eine eigenes ContextMenu funktioniert nur dieses, logisch. Um beides zu kombinieren wie hier
https://docs.microsoft.com/de-de/dotnet/framework/wpf/controls/how-to-use-spell-checking-with-a-context-menu beschrieben muss ich mein ContextMenu ergänzen und brauche dafür das Event.
Was mache ich falsch?
hallo Abt,
vielen Dank für die Mühe. Dadurch, das pro node nur ein Validierungsfehler
und keine Exception kommt hatte ich keinen Ansatz und habe die letzten beiden
Jahre mit 4.0 gearbeitet.
Ich habe die Zeile eingefügt und es funktioniert wie erwartet.
Danke. 👍 😁
verwendetes Datenbanksystem: MS SQL (hierfür nicht relevant)
Ich erstelle seit 2012 BMEcat-Dateien und parse diese im Anschluss gegen eine DTD.
Mit der Umstellung auf das .NET Framework 4.7.1 wird plötzlich die DTD ignoriert. Mit
der .NET Framework Version 4.5.1 funktioniert es noch. Bei allen Versionen ab 4.5.2
kommen dann die Fehler.
Lasse ich den Parser mit folgendem SourceCode:
XmlReaderSettings rdrSet = new XmlReaderSettings();
rdrSet.DtdProcessing = DtdProcessing.Parse;
rdrSet.ValidationType = ValidationType.DTD;
rdrSet.ValidationEventHandler += new ValidationEventHandler(rdrSet_ValidationEventHandler);
XmlReader xr = XmlReader.Create(texbCatalogFile.Text, rdrSet);
try
{
cancel = false;
while ((xr.Read()) & (!cancel)) {}
}
catch (XmlException xe)
{
parseError = true;
admCtl.showError(xe.Message,
"XML-Datei validieren");
}
if (parseError)
{
admLog.writeLog(AdminLog.LogMask.Data, "Beendet mit Fehlern!");
admCtl.showError("Die erstellte Datei darf nicht versendet werden!",
"Die Datei hat die Prüfung nicht bestanden!");
}
else
{
admLog.writeLog(AdminLog.LogMask.Data, "Fehlerlos und versandfertig!");
admCtl.showError("Die erstellte Datei kann versendet werden!",
"Die Datei hat die Prüfung bestanden!");
}
if (xr != null)
xr.Close();
auf folgende Datei los
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE buecher SYSTEM "buecher.dtd">
<buecher>
<buch isbn="nr_3-90193-3949-7" titel="Anbaggern leicht gemacht" autor="Dr. Howtodo">
Ein Anleitung zwischen Genie und Wahnsinn.
</buch>
<buch isbn="nr_3-90193-3950-2" titel="Anbaggern leicht gemacht II" autor="Dr. Howtodo">
Eine weitere Anleitung zwischen Genie und Wahnsinn.
</buch>
</buecher>
wird keine Exception geworfen, aber es werden Validierungsfehler wie
"Das buecher-Element wurde nicht deklariert." erzeugt.
Ich kann den Eintrag für die DTD in "file:buecher.dtd" ändern und das Verhalten ist absolut identisch. Ich kann auch einen ungültigen Dateinamen vorgeben und es ändert sich nichts. Mit dem .NET Framework 4.0 läuft es jedoch auch. Funktioniert die Validierung, wird bei einem falsch Dateinamen, wie erwartet, eine Exception geworfen.
Zur Vollständigkeit hier noch die DTD:
<!ELEMENT buecher (buch)*>
<!ELEMENT buch (#PCDATA)>
<!ATTLIST buch
isbn ID #REQUIRED
titel CDATA #REQUIRED
autor CDATA #REQUIRED
>
Vielen Dank für die vielen und vor allem schnellen Antworten.
Hallo Palin,
ich habe es mir angeschaut, nicht sofort verstanden und auf später verschoben.
Trotzdem Vielen Dank
Hallo Witte,
die virtuellen Maschine wäre das Genialste. Damit könnte ich auch noch Kunden helfen die auf solchen alten Maschinen unsere Uralt-Warenwirtschaft laufen lassen. Ohne Windows gibt es keine Probleme und auch keinen Wartungsaufwand. Leider ist es damals an der Netzwerkkarte gescheitert. Das alte Betriebssystem ist Prologue aus Frankreich (nicht die Programmiersprache Prolog).
Unterstützt werden folgende Netzwerkkarten:
CREALAN
NE2000
NE2000 Plus Nat. Semic.
SMC EtherCard Elite 16 Ultra (8216)
SMC EtherCard Plus Elite 16 (8013)
SMC EtherEZ (8416)
SMC EtherPower 10/100 Bus PCI (9332 DST)
INTEL Ether Express PRO/100B
Null Ethernet
Ich habe es mit "INTEL Ether Express PRO/100B" als Hardware und auch mit "Null Ethernet" versucht. Als Programmierer bin ich nicht unbedingt der VM-Fuchs. Das Betriebsystem läuft super (sogar extrem schnell) aber es kann nicht auf die Netzwerkkarte zugreifen. Damit ist dann kein Mehrplatz möglich.
Wenn Du mir da helfen könntest, oder jemanden weißt der helfen könnte?!?!?!
Aber auch Dir
Vielen Dank
Hallo gfoidl,
dein Ansatz ist tatsächlich machbar. Der Aufwand ist zwar nicht gerade klein aber ich habe es mit der AdminTables-Klasse probiert und es funktioniert. Nebenbei ist es so möglich Klassen, die in dieser Solution nicht benötigt werden, weg zu lassen und andere als Kopie radikal zu ändern.
Die breite Basis bleibt aber erhalten.
Vielen Dank.
Bis witte eventuell noch etwas einfällt, lass ich dieses Thema noch offen!
Für einen rührigen Wintersportverein habe ich vor 14 jahren eine Zeiterfassung geschrieben. Nun kann ich keine Hardware mehr auftreiben auf welcher das System läuft. Damals konnte ich viel bewährten Sourcecode aus unserer Auftragsverwltung nutzen.
Den gleichen Weg wollte ich nun wieder gehen. Aber aus "ich mach das mal eben schnell" ist inzwischen "gibts vielleich hinter dem Ural oder in Alaska noch alte Rechner?" geworden.
In all unseren Kunden-Projekten gibt es eine Klassenbibliothek mit allen Tabellendefinitionen.
Eine GUI-Klasse pflegt anhand der Feldnamen in ein Form automatisch diese SQL-Tabellen. Eine AdminTables-Klasse erstellt unds pflegt automatisch die SQL-Datenbank. Eine AdminPrint-Klasse dient zum Drucken der Stammdaten. Alle diese Klassen verweisen auf die Tabellendefinitionen und sind als Projekte in jeder Projekmappe verfügbar.
Nun mein Problem: Für die Warenwirtschaft brauche ich, sagen wir 100 Tabellen für die Zeiterfassung aber nur 3.
Ändere ich in den genannten Klassen den Verweis auf die Tabellendefinitionen wird das in allen Projektmappen wirksam. Kann ich dies irgendwie umgehen?
Mit #if/#else/#endif kann ich Source ein und ausblenden. Dies ist mir aber zu unübersichtlich und stört vor allem das Kundengeschäft. Die Zeiterfassung ist Hobby und soll es auch bleiben.
Gibt es eine Möglichkeit unterschiedliche Source-Dateien zu benutzen? Die Struktur bleibt ja gleich, nur die Anzahl ändert sich.
Ich habe das Beispiel einer SOAP-Anbindung, welches als Konsolenanwendung lief, in eine Klassenbibliothek portiert.
Als erste Aktion wird mit einem Usernamen und seinem Passwort ein AuthentificationToken abgeholt.
Starte ich dieses login aus einer WindowsForm heraus bekomme ich 2 mal hintereinander folgenden Fehler, ohne das ich das Programm neu gestartet habe.
Fehlermeldung:
BindingFailure wurde erkannt.
Message: Die Assembly mit dem Anzeigenamen "Anwendung.XmlSerializers" konnte im "LoadFrom"-Bindungskontext der AppDomain mit ID 1 nicht geladen werden. Fehlerursache: System.IO.FileNotFoundException: Die Datei oder Assembly "Anwendung.XmlSerializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" oder eine Abhängigkeit davon wurde nicht gefunden. Das System kann die angegebene Datei nicht finden.
Danach erhalte ich einen gültigen Token und die Anwendung läuft ganz normal weiter. Ich habe die Diensverweise mehrfach aktualisiert und auch den Namespace geändert.
Das Verhalten ist immer identisch. Die Konsolenanwendung läuft weiterhin ohne Fehler.
Es liegt vermutlich nur am Debug. Im Release gibt es diesen Fehler nicht!
Vielen Dank,
jetzt kann ich ohne Bauchschmerzen weiter unter x64 coden. 👍
Hallo FZell,
entschuldige bitte, auch da hatte ich keinen Unterschied gefunden.
Als Gegenbeweis habe ich eben mal alle Haken unter x64 gesetzt und siehe da: Jetzt werden Fehler geworfen. Warum verhalten sich die beiden Debugger so unterschiedlich?
Gibt es eine Beschreibung für die Bedeutung der einzelnen Punkte?
Wenn nicht, kannst Du mich bitte kurz einweisen?
Vielen Dank
Ich finde keine Unterschiede unter Debugging\Allgemein. Folgende Einstellungen sind an beiden Maschinen identisch gesetzt:
Vielen Dank für Euer reges Interesse. Ich muss das ganze noch etwas präzisieren. Es passiert offensichtlich nur in WindowsFormsAnwendungen.
Die Art des Fehlers spielt anscheinend keine Rolle. Hier ein Beispiel für Index out of range:
namespace x64WindowsFormsAnwendung
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
int[] iA = new int[12];
for (int i = 0; i < 20; i++)
iA[i] = 0;
}
}
}
Unter x86 kommt die Exception logischerweise bei i = 12.
Unter x64 kommt keine Exception aber ein Abbruch bei i = 12 im Trace, die Form wird gedoch immer komplett aufgebaut. Kapsel ich den Code mit try - catch wird die Exception korrekt geworfen. Muss ich unter x64 den gesamten Code kapseln um ohne Trace alle Fehler zu finden?
Dieses Verhalten ist bei mir völlig unabhängig von der Zielplattform.
Der Debugger von VS 2010 läuft unter Win 7 Pro x86 wie erwartet:
er hält an und dokumentiert den Fehler.
Unter Win 7 Ultimate N x64 verhält er sich gänzlich anders:
In dem identischen x86-Project werden Anweisungen unterhalb einer Cast- und Argumentexception einfach nicht ausgeführt und die Anwendung läuft im debug-Modus ohne Fehlermeldung weiter.
Im Release-Mode werden die Exceptions wieder korrekt geworfen.
Beide Entwicklungsumgebungen sind auf dem aktuellen Stand (siehe Anlage).
Danke! Das ging schnell und funktioniert auf anhieb. Danke
Ich möchte gerne beim Betreten einer Zelle einer DataGridViewTextBoxColumn auf einen Platzhalter (~) springen. In einer normalen TextBox erziele ich dies durch:
private void textBox1_Enter(object sender, EventArgs e)
{
int pos = textBox1.Text.IndexOf("~");
if (pos > -1)
textBox1.Select(pos, 1);
}
Der Cursor springt im Text "Der Würfel hatte die Farbe ~." auf die Tilde, ich kann Die Farbe eingeben und fertig.
In einem DataGridview kann ich mir die TextBox durch das Ereignis EditingControlShowing beschaffen.
private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
TextBox txtBox = (TextBox)e.Control;
int pos = txtBox.Text.IndexOf("~");
if (pos > -1)
txtBox.Select(pos, 1);
}
Trotzdem wird beim Betreten der Zelle der gesamte Text markiert.
Auch das zusätzliche Ereignis TextBox.Enter, welches sich einbinden lässt und
auch ausgelöst wird, schafft keine Abhilfe.
private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
txtBox = (TextBox)e.Control;
txtBox.Enter += new EventHandler(txtBox_Enter);
}
void txtBox_Enter(object sender, EventArgs e)
{
int pos = txtBox.Text.IndexOf("~");
if (pos > -1)
txtBox.Select(pos, 1);
}
private void dataGridView1_CellLeave(object sender, DataGridViewCellEventArgs e)
{
if (txtBox != null)
txtBox.Enter -= txtBox_Enter;
}
Mir sind nun die Ideen ausgegangen.
das wars
Vielen DANK!!!
Nach dem gestern keine Projekteigenschaften in meinem VS2008 mehr angezeigt wurden habe ich VS2008 deinstalliert und VS2010 installiert. Ich schreibe die Programme hauptsächlich in C#.
Mit VS 2005 und 2008 konnte ich ItelliSense nutzen, in dem ich z.B. für eine TextBox "txtBox.N" eingegeben habe. IntelliSense hat 'txtBox.Name' gefunden und ich konnte sofort mit der nächsten Taste (Leerzeichen) die Codevervollständigung nutzen.
In VS2010 wird ".Name" auch sofort gefunden, ist jedoch nur eingerahmt. Ich muss erst mit den Curosrtasten die Auswahl aktiv machen.
Bei der Eingabe der ersten Buchstaben einer globale Variable kommt die Vorschlagsliste erst nach dem ich nach "Ctl+Space" beide Tasten losgelassen habe. Vorher konnte "Ctl" gedrückt bleiben.
Kann man irgendetwas einstellen? Ich habe in den Extras\Optionen nichts gefunden.
Da ich nur noch halb so schnell bin wäre ich für Hilfe sehr, sehr dankbar.
Vielen Dank für Deine Antwort,
Du hast mich auf die richtige Spur gebracht.
Leider ist unter Windows 7 die odbc.ini anscheinend gänzlich anders aufgebaut.
Zumindest kann ich keine Zusammenhänge erkennen.
Unter http://msdn.microsoft.com/de-de/library/ms190234%28SQL.90%29.aspx habe ich eine Anleitung für Escape-Sequenzen gefunden. Der Assistent mischt sich nun nicht mehr ein!
SELECT * FROM tabelle WHERE (datum > {d '2010-07-20' })
verwendetes Datenbanksystem: ODBC-Datenquelle Criteria 3.4
Die genannte ODBC-Datenquelle erwartet eine Datumsangabe in der Form 'yyyy-MM-dd'.
Bei der Programmierung ist dies kein Problem. Möchte man aber im Server Explorer "mal schnell" eine Abfrage testen wird das Datumsformat gewandelt. Plötzlich steht dann in der Abfrage 'd/MM/yyyy'. Kann man das abschalten ?(
verwendetes Datenbanksystem: XML
Offensichtlich habe ich "Globalization" und "CultureInfo" noch nicht verstanden.
Wenn ich ein .NET Programm starte, wird die aktuelle Kultur automatisch bestimmt.
So die Theorie, nun die Praxis:
Lasse ich den Inhalt eines DatagridViews über dessen DataSet und dem XMLWriter schreiben steht folgendes (bei einem Dezimalwert 0,50) im XML-File:
datSet.WriteXml("test.xml");
<?xml version="1.0" standalone="yes"?>
<NewDataSet>
<Value>
<Nr>1</Nr>
<Name>Test</Name>
<Wert>0.5</Wert>
</Value>
</NewDataSet>
Nach meiner Meinung wurde doch bereits hier die CultureInfo (en-US) angewandt.
Auffällig wird dies bei einem
datSet.Clear(); und datSet.ReadXml("test.xml");
Denn nun wurde aus 0.5 5,00.
Wann gilt nun welche Kultur? Was passiert auf einem englichen System?
Heureka 🙂
public class DatagridviewWOEnter : DataGridView
{
private int actCol;
private int actRow;
protected override void OnCellEnter(DataGridViewCellEventArgs e)
{
actCol = e.ColumnIndex;
actRow = e.RowIndex;
base.OnCellEnter(e);
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.Enter)
{
if (actCol == this.Columns.Count - 2)
{
CurrentCell = Rows[actRow].Cells[actCol + 1];
return true;
}
else
{
if ((actCol == this.Columns.Count - 1) && (actRow < Rows.Count - 1))
{
CurrentCell = Rows[actRow + 1].Cells[actCol - 1];
return true;
}
}
}
return base.ProcessCmdKey(ref msg, keyData);
}
}
Vielen Dank an alle Beteiligten.
Michael
Hallo MarsStein, Hallo Jürgen,
hier ein kurzer Zwischenbericht:
Laut Microsoft werden die Keyereignisse vor KeyDown in der Reihenfolge
und man dachte es wäre nur eine Kleinigkeit...
8o
Nun habe ich eine neues Problem. Meine neue Klasse:
public class TextBoxWOEnter : TextBox
{
protected override bool IsInputKey(Keys keyData)
{
base.IsInputKey(keyData);
if (keyData == Keys.Enter)
{
return true;
}
else
{
return base.IsInputKey(keyData);
}
}
}
lässt sich nun nicht casten:
private TextBoxWOEnter txtBox;
private void dgvExcel_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if (actCol > lastCol)
{
txtBox = (TextBoxWOEnter)e.Control;
txtBox.Name = string.Format("col{0}", actCol);
txtBox.KeyDown += new KeyEventHandler(txtBox_KeyDown);
}
}
Das Objekt des Typs "System.Windows.Forms.DataGridViewTextBoxEditingControl" kann nicht in Typ "TextBoxWOEnter" umgewandelt werden.
Michael
danke Jürgen,
ich werde das gleich mal probieren. 🙂
Ich möchte in einem DatagridView mit mehreren Spalten nur die beiden letzten Spalten editieren. Hierbei soll der Cursor von der vorletzten Spalte nach [Enter] in die letzte Spalte springen. Von hier aus mit [Enter] in die nächste Zeile auf die vorletzte Spalte und so weiter.
Wenn noch kein EditingControlShowing-Ereignis stattgefunden hat, kann ich dies mit:
private void dgvExcel_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
if (actCol == lastCol + 1)
{
dgvExcel.CurrentCell = dgvExcel.Rows[actRow].Cells[actCol + 1];
e.Handled = true;
}
else
{
if ((actCol == lastCol + 2) && (actRow < dgvExcel.Rows.Count))
{
dgvExcel.CurrentCell = dgvExcel.Rows[actRow + 1].Cells[actCol - 1];
e.Handled = true;
}
}
}
}
abfangen. Nach EditingControlShowing habe ich in der ermittelten Textbox ein Ereignis KeyDown registriert. Hier werden alle Eingaben gemeldet. Aber nicht die Enter-Taste. Was kann ich tun?
Hallo frisch,
danke für Deine Mühe. Der Datentyp in der Datenbank ist "Text". Die ominöse Verwandlung passiert nicht in der Datenbank sondern in der RichTextBox. Wie kann ich anders als durch das Laden des Textes die Codepage festlegen?
Gruß Michael
Ist RichTextBox nicht gleich RichTextBox?
Ich habe in der gleichen Projektmappe zwei Projekte mit einem Rtf-Feld. Im ersten Projekt dient das Rtf-Feld der Umwandlung von Plain-Text in Rtf-Text:
...lese plainText
rtfBox.Text = plainText;
saveText = rtfBox.Rtf;
...speicher Text (in MS-SQL-Datenbank)
Im zweiten Projekt lese ich diesen Rtf-Text wieder ein und merke mir den aktuellen Inhalt:
... lese rtfText
string orgText = leseText;
rtfBox.Rtf = leseText;
Im Anschluß ist aber orgText != rtfBox.Rtf
Beispiel:
plainText:
"2006 zurück"
orgText:
"{\rtf1\ansi\ansicpg1252\deff0{\fonttbl{\f0\fnil\fcharset0 Tahoma;}}
\viewkind4\uc1\pard\lang1031\f0\fs20 2006 zur"fcck\par
}"
rtfBox.Rtf:
"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Tahoma;}}
\viewkind4\uc1\pard\lang1031\f0\fs20 2006 zur'fcck\par
}"
Wieso ist "ansicpg1252" plötzlich nicht mehr da? Warum wird der Umlaut unterschiedlich gespeichert?
Wenn die neue Version gespeichert wurde, bleibt diese dann auch erhalten.
Danke für die hier gefundene Beschreibung der Rechte. Endlich habe ich es verstanden.
Ich habe das Problem, daß ich nur für Benutzer, einen ODBC-Treiber zu einer Prologue-Datenbank Criteria über ein virtuelles Verzeichnis anlegen kann. Ich habe also einen neuen Anwendungspool angelegt und den Benutzer zugewiesen. Wie kann ich aber nun meine Anwendung aus dem DefaultAppPool in meinen neuenPool verschieben?
Manchmal muss man sich nur zwingen ein Thema zu formulieren um dessen Lösung zu finden: PrintPageEventArgs.PageSettings.PrintableArea
Vielen Dank!
Aus einem PrintPageEventArgs kann ich die aktuellen MarginBounds auslesen. Mit einem PageSetupDialog kann ich diese MarginBounds sogar setzen. Woher bekomme ich aber die vom aktuellen Drucker vorgegebenen MarginBounds? Ein Laser-Drucker hat ja z.B. schmalere Seitenränder als ein Tintenstrahldrucker. Ein Endlosdrucker bekommt 2 Zeilen mehr auf eine Seite. Hat jemand einen Rat?
Vielen Dank für die schnelle Antwort. Ich brauche die Stringlänge. Natürlich kann der String auch genau aus einem Zeichen bestehen. Gleich bei welcher Schrift, sollte eigentlich die Gesamtbreite eines Wortes mit gleichen Buchstaben proportional zu seiner Anzahl sein.
In einem anderen Forum fand ich inzwischen eine mögliche Diskrepanz zwischen DrawString-Breite und der mit MeasureString ermittelten Breite, wenn als StringFormat nicht mit StringFormat.GenericTypographic gearbeitet wird. Warum dies so ist weiss ich noch nicht.
StringFormat sf = new StringFormat(StringFormat.GenericTypographic);
sf.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;
Diese Kombination liefert eineindeutige Ergebnisse bei der Vermessung von Strings.
Ich sitze nun seit über 5 Stunden an diesem Problem und habe keine Lösung gefunden. Laut MS hat StringFormatFlags.MeasureTrailingSpaces geneu die inverse Funktionalität. Aber ob mit oder ohne dieses Flag, jede Breite einer beliebige Anzahl von Zeichen im String, wird bei konstantem Font mit einem konstanten Offset zurückgegeben. Ich brauche für einen RTF-Druck jedoch nur die exakte Zeichen(Wort)-breite. Wie geht das?
Der folgende Code:
//StringFormat sf = new StringFormat(StringFormatFlags.MeasureTrailingSpaces);
StringFormat sf = new StringFormat();
sf.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;
float l = e.Graphics.MeasureString(line, actFont, 60000, sf).Width;
l = l / (float)line.Length;
liefert für jede Stringlänge (Line = "a", "aa", "aaa") andere Zeichenbreiten.