hallo zusammen,
hab´s inzwischen herausbekommen; hier die lösung, falls zukünftig jemand mal ein objekt in ein XML Datenfeld serialisieren möchte.
// Datenzugriffe
BindingSource bds = GetBindingSource("meineDatenquelle");
DataRowView viewRow = (DataRowView)bds[bds.Find("Kriterienspalte", einKriterium)];
// Serialisierer erstellen
XmlSerializer serializer = new XmlSerializer(typeof(meinObjekt));
// StringWriter erstellen! denn es soll ja nicht in eine Datei geschrieben werden
StringWriter writer = new StringWriter();
// Serialisieren...
serializer.Serialize(writer, meinObjekt);
// ...und das Ergebnis aus dem Writer in das gewünschte Datenfeld eintragen
viewRow["zielSpalte"] = writer.ToString();
// Änderungen in der BindingSource übernehmen
bds.EndEdit();
und falls man es auch zur Deserialisierung verwenden möchte, geht das so:
if (viewRow["zielSpalte"] != DBNull.Value) try
{
StringReader reader = new StringReader(viewRow["zielSpalte"].ToString());
XmlSerializer serializer = new XmlSerializer(typeof(meinObjekt));
meinObjekt = serializer.Deserialize(reader) as meinObjekt;
}
catch {}
viel erfolg
ron
@herbivore,
naja, weil der deserialisierungskonstruktor ja eine vorgeschriebene signatur hat.
beim aufruf würde also ein für meine zwecke unvollständiges objekt zurückkommen.
mein eigentliches objekt wird aber über einen microkernel mit völlig anderer signatur erzeugt und soll eben wie gesagt nur ein paar eigenschaftswerte über die deserialisierung ergänzt bekommen.
hab mich hier mal reingelesen, klingt aber ein bisschen zu kompliziert:
http://www.microsoft.com/germany/msdn/library/net/FortgeschritteneThemenDerNETSerialisierung.mspx?mfr=true
ziemlich weit unten wo es um **ISerializationSurrogate **geht
was meinst Du?
gruß
ron
hallo leute,
ich habe binär einige objekteigenschaften in ein varbinary datenfeld einer tabelle serialisiert.
das geschieht über angepasste serialisierung:
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("DisplayFlags", _DisplayFlags);
info.AddValue("Selection", _SubView.Selection);
info.AddValue("HiddenGridColumns", _DataGrid.HiddenColumns);
}
da es sich hier ja aber nur um ein paar selektive eigenschaften des gesamten objekts handelt, stellt sich mir die frage, wie deserialisiere ich eigentlich diese information in ein bestehendes objekt?
bei der deserialisierung will ich ja mit einem eigenen konstruktor (kein Deserialisierungs-Konstruktor) das objekt erzeugen und dann **ergänzend eine deserialisierung **für **einige eigenschaften **vornehmen.
wenn ich jetzt also der teilserialisierten klasse z.B. nachstehende methode hinzufüge:
public void SetObjectData(SerializationInfo info)
{
_DisplayFlags = (eDisplayFlags)info.GetByte("DisplayFlags");
}
dann weiss ich jetzt aber nicht weiter, denn woher kommt die SerializationInfo, mit der ich von aussen diese Methode aufrufen könnte?
danke für eure hilfe
ron
hallo helferleins!
ich würde gerne ein objekt mit angepasster serialisierung (also eine ISerializable-Implementierung) in ein Datenfeld einer SQL server 2005 Tabelle schreiben.
folgender ansatz klappt nicht (z.B. bei neuen Datensätzen, die ich anlege, weil der stream nicht über ein DBNull value erzeugt werden kann:
DataRowView viewRow;
BindingSource bds = GetBindingSource("USERVIEW");
viewRow = (DataRowView)bds.AddNew();
viewRow["RecordID"] = Guid.NewGuid();
// Create a stream on column [XML]
MemoryStream mStream = new MemoryStream((Byte[])viewRow["XML"]);
XmlSerializer serializer = new XmlSerializer(typeof(IView));
serializer.Serialize((mStream, view);
danke für eure hilfe
gruß
ron
hi coder
Habs auf die schnelle als n:n Beziehung realisiert, aber ich denke, das ist nicht die optimale Lösung.
warum soll das nicht die optimalste lösung sein?
in einer relationalen datenbank sind relational abgelegte daten das performanteste, was du machen kannst, zumal wenn es nur kleine informationseinheiten wie integers sind.
das als objekt oder irgendwie codiert abzuspeichern und zur laufzeit wieder auseinanderzuklamüsern ist immer der schlechtere weg. erst recht, wenn du danach suchen willst.
jedenfalls imh
gruß
ron
hi netblade,
meine technik basiert wie gesagt darauf, dass ich ein attribut in das tag jedes knotens lege, das ihn eindeutig identifiziert (z.b. den primärschlüssel des eintrags in der datenbank, das ihn eindeutig kennzeichnet.
diese spalte ist im datagridview ebenfalls vorhanden; wenn sie nicht optisch gebraucht wird, ist ihre eigenschaft visible=false.
das ereignis, das für die synchronisation sorgt, ist bei uns das ereignis AfterSelect der treeview. Dort ist aus den TreeViewEventArgs e.Node der aktuell gewählte Knoten.
das ereignis sucht den passenden eintrag im datagridview (hier dgv genannt) mit:
foreach (DataGridViewRow row in dgv.Rows)
{
if ((Guid)row.Cells["RecordID"].Value == e.Node.Tag)
if (!row.Selected) row.Selected = true;
}
hierbei ist im Beispiel "RecordID" der Name der Spalte, in der nach dem Tag-Value gesucht wird.
alternativ dazu könnte man auch in der dem datagridview zugrundeliegenden BindingSource direkt die Position setzen. Dazu verwendet man die Methode Find() und ihren Rückgabewert als Positionsindex:
((BindingSource)dgv.DataSource).Position = ((BindingSource)dgv.DataSource).Find("RecordID", e.Node.Tag);
Da das DataGridView an der BindingSource "hängt", reagiert es auch auf dessen Positionsänderung.
Letzteres ist bei vielen Datensätzen der bessere Weg, da kein Schleifendurchlauf durch alle Einträge durchlaufen muss.
hth
gruß
ron
hi bionic
arbeite (ausschließlich!) auf meinem dell xps MXG061
da ist dann auch alles drauf: vs2005, vb 6.0, office 2003 prof., sql server 2000, sql server 2005, mssqlexpress, visio, project, ftp clients, etc.
sprich: eierlegende wollmilchsau... 🙂
der grund war einfach, dass ich oft auch beim kunden vorort programmiere und daher "alles" dabei haben möchte.
aus diesem grund habe ich mir als software noch MobileNetSwitch angeschafft; damit klinke ich mich mit verschiedenen profilen in die netze meiner kunden vorort ein.
würde es nie wieder anders machen - ich bin sehr zufrieden.
leistungsmerkmale:
2g arbeitsspeicher, centrino duo mit 2g taktung, 80gb festplatte, dvd brenner, 6xUSB, smartcardreader, bluetooth, etc., windows xp professional als os
ich kann allerdings dringend empfehlen,
a) ein zweites ladegerät anzuschaffen, damit man eines immer zuhause lassen kann
b) ein kabelloses desktop (hier: logitech dinovo) anzuschaffen
übrigens kann ich DELL nur wärmstens empfeheln, das preis leistungs-verhältnis ist nicht zu schlagen und der service ist ausgezeichnet!
hth
gruß
ron
hi steven,
mit data source im connection string ist der server gemeint; hast du mssql express auf dem gleichen rechner installiert, muss dort also stehen:
".[Instanzname]"
wobei bei SQL Express der Instanzname meit "SQLEXPRESS" ist.
hth
ron
hi webseal,
was zu dem von den anderen gesagten ausserdem geht, ist ein ganzes formular in ein anderes formular einzufügen:
Form childForm = new myForm()
this.ViewPanel.Controls.Add(frm);
dadurch löst du unabhängig von dem modularen charakter der anwendung auch die tatsache, dass es nicht notwendigerweise panels sein müssen, in denen sich deine funktionalen control gruppen befinden.
dabei musst du nur beachten, dass das eingebettete form die properties toplevel und dock setzt:
this.TopLevel = false;
this.Dock = DockingStyle.Fill;
gruß ron
hi stf-dir,
vielleicht wäre in deinem fall eine datagridview mit selectionmode=fullrowselect und einer textbox mit multiline=true als anzeigeelement geeigneter?
gruß
ron
hi bernd
Denn ein GUID sagt ja nichts aus darüber ob ein Datensatz schon vorhanden ist.
nee, is klar, ein datentyp sagt niemals etwas über "schon vorhanden oder nicht" aus, sondern die eigenschaft einer spalte, primärschlüssel zu sein.
und auch ein GUID kann eben als Primärspalte eingesetzt werden, was bei merge replikation bspw. sinnvoll ist.
gruß
ron
hi shabi
du kannst den schlüssel höchstens zu einer zeichenkette zusammenfügen und vergleichen, ansonsten musst du ihn getreent betrachten.
deshalb ist ein "breitgetretener" primärschlüssel auch kein gutes design.
wenn du einfluss auf die datenbank nehmen kannst tu´s und verpass den tabellen einen (künstlichen) primärschlüssel als GUID oder zähler (int).
gruß
ron
hi dragon
iss zwar ein bissi brutal aber man kann ja xp_cmdshell im trigger aufrufen. 😉
du müsstest die halt n konsolenprogramm schreiben, dem du dann vielleicht sogar noch argumente mit auf den weg geben kannst.
hier ein bsp.:
CREATE TRIGGER trg_i_Datei
ON dbo.DATEI
AFTER INSERT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for trigger here
declare @s varchar(20)
select @s = Kennung from inserted
set @s = 'c:\temp\kannweg.cmd ' + @s
exec master.dbo.xp_cmdshell @s
END
GO
wenn ich es richtig in erinnerung habe, muss man aber der sql serverinstanz oder der db noch irgendwo sagen, dass erweiterte SP´s oder command shell aus triggern heraus erlaubt sind (kann mich aber irren...)
gruß
ron
hi simon
eigenschaften des projekts, registerlasche "Anwendung", Schalter "Assemblyinformationen...", Option "Anwendung COM-sichtbar machen"
gruß
ron
hi cullmann,
Meine frage ist jetzt: Warum sollte ich wieder auf das interface casten (ICompressible icDoc = doc as ICompressible; ) wenn ich alle Methoden doch direkt über die doc instanz ansprechen kann.
ja schon, aber da du die variable doc ja nicht über einen activator oder eine assembly direct aus einem interfacetyp erzeugt hast, weißt du zur laufzeit ja gar nicht, ob die variable doc die fähigkeiten dieses interface auch wirklich implementiert.
in anderen worten: wenn du zur laufzeit eine variable kfz als fahrzeug initialisierst, weisst du noch lange nicht, dass es ein mähdrescher ist und über die fähigkeit Mäh() verfügt.... 😉
Ausserdem finde ich offengesagt eleganter, statt auf != null zu prüfen, die bedingung gleich zu formulieren als:
if (doc is IStorable)...
gruß
ron
hi philipp
die fragestellung ist ein bissi unpräzise - willst du jetzt excel oder nur "a la excel"??
wenn du excel willst, bietet die das objektmodell von excel bzw. vsto. die geeigneten eigenschaften an mit bspw.
Selection.Cells[3, 3]
willst du nur a la excel dann... tjy dann stell deine frage nochmal mit dem gewünschten ziel; was darf´s denn sein? sql server? access? oracle?
oder vielleicht nur eine DataTable in einem DataSet?
und wenn du´s nur darstellen und nicht speichern willst würde vielleicht schon ein datagridview reichen, dass auf einer bindingsource operiert die wiederum nur mit deiner liste in verbindung gebracht werden müsste.
gruß
ron
normalerweise ist dein datagrid mit einer bindingsource verbunden.
es dürfte schon reichen, das property position dieser binding source auf den gewünschten eintrag zu setzen.
grundsätzlich würde ich aber mal überdenken, ob das alles so der richtige weg ist, denn in einer binding source bzw. im datengitter ist die sortierung ja stark abhängig von dem, was der benutzer so mit dem datengitter anstellt... 🙂
ruß
ron
hi bär,
nichtmal access selbst bietet für die gesamte datenbank den befehl "speichern unter". da wirst du wohl auch unter c# eine dateikopier-operation durchführen müssen.
das versehen mit einem passwort geschieht in access über "kennwort festlegen". dieser befehl ist über die vsto (die ja letztlich nur das vba objektmodell kapselt) erreichbar.
gruß
ron
hi andreas,
die combobox hat für diesen zweck die eigenschaften ValueMember (=geschriebener Wert) und DisplayMember (gezeigter Wert).
diese beziehen sich auf die binding source der combobox (also auf ihre eigene datenquelle)
die databindings der combobox arbeiten wie bei anderen steuerelementen auch. die gebundene eigenschaft sollte dann SelectedValue sein.
gruß
ron
hi markus,
also, die vierte überlegung ist die beste 😉
darüberhinaus haben wir unser framework so ausgelegt, dass zu jeder select stored procedure die passende update/insert prozedur existiert.
es gibt also bspw. eine SP namens udp_s_Kunde für das select.
für update UND (!) insert gibt es eine udp_u_Kunde.
diese entscheidet selbsttätig, ob es den gesuchten eintrag schon gibt (=>where klausel) oder ob er noch nicht vorhanden ist (=>insert statement)
so bekommt unsere klasse zur laufzeit die erzeugung des insert und update command hin, indem sie in beiden fällen nur noch das "s" (wie "select") in "u" verwandelt (wie "update")
diese klasse heisst "BusinessContext" und ist einerseits die implementierung eines interface "IBusinessContext" und andererseits die basisklasse aller mit daten operierender klassen.
Das hat den Vorteil es ist egal welches Objekt ich übergeben der SELECT paßt für alle
Objekte die so aufgebaut sind wie die Kunden Klassen.
unser business context baut diesen vorteil also u.a. dahingehend aus, dass keine select/insert/update-commands irgendwie in der endklasse (Kunde, Person, Dokument, etc.) bekannt sind und die datenbeschaffung und -aktualisierung nur auf der datenbankseite geregelt wird.
hth
ron
hi shorty
sollen ergebnisse der aggregatfunktionen selbst wieder als kriterien verwendet werden, brauchst du dazu die HAVING klausel nach der gruppierung:
select
sum(dauer)
from
sitzung
where
(id = 66)
group by
month(beginn)
having
sum(dauer) > 250
gruß
ron
hi markus,
mal die "kurze" antwort vorweg:
ich würde dem formular nicht die tabelle angeben, also wäre der generic aufruf imh der bessere.
jetzt die lange antwort 😁
wenn du schon "hartcodiert" in die klasse kunde reinschreibst, dass es bei der pk-spalte um "id" geht, die ein uniqueidentifier ist etc. warum machst du das nicht gleich als readonly properties, die die klasse kunde im constructor mit den entsprechenden werten belegt.
ich sehe hier offengesagt keinen grund, attributes & reflection zu verwenden.
und im günstigsten fall bist du auch der datenbank-architekt und dann heisst die pk spalte sowieso IMMER "id" und ist IMMER ein uniqueidentifier und dann gibt es natürlich noch ein paar zusätzliche codeeinsparungen...
ist aber nur meine bescheidene meinung.
hth
gruß
ron
hallo
also, falls das jemand mal interessiert:
TableLayoutPanels sind in vererbten Formularen nicht veränderbar.
unabhängig von ihrem Modifizierer.
Ist somit wohl ein Leistungsmerkmal (sprich: feature) von .NET. 😁
gruß
ron
hi folks,
habe ich das (z.B. hier: http://www.developersdex.com/sql/message.asp?p=1119&r=5529401) richtig verstanden, dass der DataAdapter keine default values der datenbank unterstützt, obwohl man mit FillSchema() Angaben zur Tabellenstruktur abgerufen hat?
wer braucht dann noch ein FillSchema()?
eine Datenspalte namens [Created] not null mit getdate() als default wirft in meiner anwendung eine NoNullAllowedException.
wie habt ihr sowas gelöst?
gruß
ron
hi folks,
wir haben uns hier immer mal wieder in ein paar fallen hineinmanövriert, die ich mal als Event Bouncing bezeichnen möchte:
Ein event löst ein event aus, das ein event auslöst, das ein event auslöst....
mit ein bisschen pech ist in der folgekette aller events das ursprüngliche event auch wieder mit drin und dann gibt´s ereignisbehandlungen bis zum sanktnimmerleinstag.... 🙂
wir halten es daher für sehr wichtig, sich vor dem codieren unbedingt gedanken über die ereignisarchitektur seiner klassen gedanken zu machen, denn die delegaten und ereignismöglichkeiten von .net laden zu allerlei tollen dingen ein, die man manchmal besser (sprich: auf direkterem prozeduralen weg) gelöst hätte.
gruß
ron
hallo jürgen,
sorry, aber ich bin ja nicht zum ersten mal hier; die suche hat leider nichts passendes ergeben, sonst hätte ich hier kein thema erstellt...
das problem ist auch nicht, dass protected/public grundsätzlich nicht greift, sondern dass mir das ein problem verschachtelter container-steuerelemente zu sein scheint: das oberste container element (Panel) kann ich wie gesagt prima in der ableitung verändern, nicht aber die elemente des TableLayoutPanels, das aber ebenfalls Protected Internal ist.
hi folks,
ich habe ein Form namens "Desktop";
darin befindet sich ein Panel "DesktopPanel" und im Panel ein TableLayoutPanel "GroupTable". Für alle diese Elemente sind die Modifizierer auf Protected Internal gesetzt.
In einem geerbten Form, das also von "Dektop" erbt, kann ich im Designer nur das DesktopPanel verändern (also z.B. um weitere Controls ergänzen), die GroupTable kann ich nicht ändern.
Wieso? Übersehe ich hier etwas?
Danke für eure Hilfe.
ron
hi hendrik,
da du dir irgendwo merken musst, welche benutzer die löschung akzeptiert haben, brauchst du noch eine tabelle [dbo].[Loeschung] mit bspw. einer spalte [Angenommen] (bit) default = 0 not null
mit einem left join auf
(x.RecordID = loeschung.xID) where (loeschung.angenommen = 0)
findest du dann alle, die die löschung noch nicht angenommen haben.
gruß
ron
hi svenson,
ja, das stimmt, das geht, aber verlagert das problem nur einen weiteren methodenaufruf höher: Auch in diesem fall muss ja der typ EXPLIZIT bei aufruf der methode angegeben werden.
naja, habe jetzt meinen microkernel um eine überladung von GetInstance erweitert, der nicht generisch ist, wär aber trotzdem eine tolle neue erkenntnis gewesen, wenn sowas ginge 😉
thanx
ron
hi folks,
gibt es eine möglichkeit, das argument einer methode als typ an einen generischen methodenaufruf zu übergeben?
folgendes z.b. geht nicht:
private IBusinessContext SetContext(Type type)
{
return (IBusinessContext)microKernel.GetInstance<type>();
}
weil type ja nur eine variable ist und nicht den (z.B.) schnittstellentyp nennt, der erwartet wird.
also nochmal in anderen worten: gibt es syntaktisch in C# überhaupt die möglichkeit, die angabe des generic type aus einer variablen zu bilden?
danke
ron
zum Beispiel das ich bei falscher Eingabe eine Meldung kommt, die Komplexer formatiert ist
Dafür gibt es doch dann den ErrorProvider;
die formatierung von ToolTip und ErrorProvider sind in gewissen Grenzen ja auch vornehmbar;
und im "schlimmsten" falle schreibst du deine eigene klasse, die von ToolTip oder ErrorProvider erbt.
hi mipa,
du musst die komplette größe verwenden:
myform.Size = new Size(20, 40);
willst du nur einen wert ändern, bedeutet das entsprechend:
myform.Size = new Size(myForm.Size.Width, 40);
hi marcus,
die angemessene technik wäre eigentlich die klasse ToolTip, zur entwurfszeit in der toolbox verfügbar, gruppe "Allgemeine Steuerelemente"
hi folks,
ich habe folgendes Phänomen mit einer DataGridView.
Um ein Drag & Drop zu ermöglichen, fange ich mit nachstehendem Code das MouseMove-Ereignis ab:
private void DataGrid_CellMouseMove(object sender, DataGridViewCellMouseEventArgs e)
{
if (((e.Button & MouseButtons.Left) == MouseButtons.Left) && (e.Clicks < 2))
tu_Irgendwas;
}
Das führt aber leider dazu, dass der ERSTE Doppelklick in einer ANDEREN Zeile als die aktuell ausgewählte nicht mehr verarbeitet wird; ein Doppelklick wird jetzt nur verarbeitet, wenn er in der Zeile geschieht, die ohnehin bereits ausgewählt ist.
Das stört natürlich; hat jemand von euch eine Idee?
Ausserdem ist witzigerweise das Argument e.Clicks in obigem code auch bei einem Doppelklick immer 0; wozu gibt es das dann?
danke & gruß
ron
hi fzelle
um geschwindigkeit geht es hierbei eigentlich weniger, sondern vielmehr darum, dass meiner erfahrung nach sql anweisungen aus wartungsgründen in compiliertem code nichts zu suchen haben 😉
gruß
ron
hi sven
du solltest lieber eine user defined function nehmen statt ein argument eine stored procedure als OUT zu "vergewohltätigen":
CREATE FUNCTION meineSumme (
@Datum datetime,
@Name varchar(10)
)
RETURNS float
AS BEGIN
declare
@result float
set @Summe=(Select SUM(Summenfeld) from .... where Name=@Name...
return @result
END
im code rufst du dann ganz normal das ergebnis ab mit:
sqlCommand.CommandType = System.Data.CommandType.StoredProcedure;
sqlCommand.CommandText = "meineSumme";
// Init return object
object result = DBNull.Value;
SqlParameter returnVal = new SqlParameter("RETURN_VALUE",SqlDbType.Variant);
// Init return value parameter
returnVal.Direction = ParameterDirection.ReturnValue;
sqlCommand.Parameters.Add(returnVal);
// Execute the command
_Affected = sqlCommand.ExecuteNonQuery();
result = sqlCommand.Parameters["RETURN_VALUE"].Value;
gruß
ron
hi folks,
wann ist eurer meinung nach eine methode, wann ein property sinnvoller, um von einer klasse nach draussen etwas bereitzustellen?
vorausgesetzt sei mal, es handele sich in beiden fällen um gleich wenig oder viel code.
beispiel: eine klasse soll eine reihe von BindingSource elementen bereitstellen und alle liegen intern im rahmen eines dictionary vor.
ist es eurer meinung nach sinnvoll, das dictionary zu veröffentlichen:
public Dictionary<string, BindingSource> BindingSource
{
get { return _BindingSource; }
}
oder besser, eine methode zu implementieren:
public BindingSource GetBindingSource(string tableName)
{
return this.BindingSource[tableName];
}
danke für eure meinung
ron
in sql umgesetzt:
select
min(Zahlenspalte) + 1
from
[Tabellenname] t
where not exists (
select [irgendeineSpalte]
from [Tabellenname] t1
where t1.Zahlenspalte= t.Zahlenspalte+ 1
)
gruß
ron
ich wusste doch, ich hatte da irgendwann nochmal was cooleres gesehen.
bist der held, herbivore, danke!
(du natürlich auch, peter!) 😉
hi leute,
ich würde gerne zur laufzeit prüfen, ob eine objektvariable einen bestimmten schnittstellentyp implementiert.
im nachfolgenden beispiel soll ein Control bspw. herausfinden, ob das Formular, in dem es sich befindet, die Schnittstelle IDBContainer implementiert.
natürlich kann man über ein try-catch herausfinden, ob das casting geklappt hat:
private IDBContainer parentContainer;
try
{
parentContainer = (IDBContainer)FindForm();
}
catch { /* war wohl nix */ }
die frage ist: geht das auch eleganter?
ist es legitim zum bsp. nachstehendes zu machen:
if (FindForm().GetType() == typeof(IDBControl))
{
// und hier geht´s dann cool zur Sache ... :-)
}
danke für eure meinung.
gruß
ron
hi bertl
folgende lösungsansätze:
*bist du bei deinem verbindungsversuch immer noch lokal (auf der gleichen maschine?)
wenn nicht musst du über die oberflächenkonfiguration remoteverbindungen (am besten named pipes und tcp/ip) aktivieren
*installier das (ebenfalls kostenlose) management paket und dann hast du eine verwaltungsoberfläche, in der du das kennwort des sa garantiert ändern kannst. (http://www.microsoft.com/downloads/details.aspx?FamilyID=c243a5ae-4bd1-4e3d-94b8-5a0f62bf7796&DisplayLang=de) *auf welche datenbank versuchst du dich denn zu verbinden? ist die denn schon angehängt? oder bist du sicher, dass du die master ansprichst? *von wo aus kommst du denn? code? hast du mal versucht, mit access, excel oder odbc draufzugehen?
hoffe es waren ein paar neue denkanstöße dabei
gruß
ron
hi heimi,
war ein paar tage offline, daher erst jetzt eine antwort:
also den satz "Ich habe jetzt überall den Typ dateTime genommen" verstehe ich so, dass du jetzt die spalten beibehalten hast, aber alle zum typ datetime gemacht hast.
bei mir ist es so, dass ich sagen wir mal eine tabelle namens [ACTIVITY] habe, die im einfachsten falle lediglich über die spalten
[Typ], tinyInt; (0-Pause, 1-Arbeitszeit, 2-Urlaub, 3-Krankheit, etc.)
[Starts], DateTime;
[Ends], DateTime
verfügen muss sowie über geeignete Fremdschlüsselspalten, um auf eine Person zu verweisen.
Wenn du bei deinem modell bleiben willst, dann solltest du zumindest die formatierung der spalten bei der ausgabe so verändern, dass dort, wo nur das datum interessiert die zeit auch nicht ausgegeben wird, bzw. dort, wo nur die zeit interessiert natürlich das datum unterdrückt wird.
hi junky,
hab deinen vorschlag probiert, aber das property Enabled des UserControls wird nicht verändert, wenn der übergeordnete container enabled ändert; daher ist es so leider nicht machbar.
schade, schien mir ne gute idee zu sein...
ich habe aber noch ein problem.
liegt eine TextBox in einem container, der disabled ist (z.B. Panel) wird zur Laufzeit
die textbox auch schön disabled dargestellt.
ist die textbox in einem usercontrol eingebettet, bleibt sie weiss, als sei sie aktiv.
bis jetzt erzwinge ich die aktualisierte darstellung mit:
protected override void OnPaint(PaintEventArgs e)
{
Textbox.BackColor = (CanFocus) ? SystemColors.Window :
SystemColors.ControlLight;
base.OnPaint(e);
}
das bremst aber ganz gehörig.
hat jemand da noch eine idee?
hi drache,
ist halt ne frage der zuständigkeiten.
in meinem fall ist die textbox an eine datenquelle gebunden, kennt ihre Datenspalte, prüft ob deren AllowDBNull-Eigenschaft wahr ist und leitet daraus einen "Ist Pflichtfeld"-Stern ab.
schon rein objektorientiert betrachtet halte ich es für bedenklich, hier eigenschaften der textbox nach aussen zu stellen, bloss damit der übergeordnete container das zeichnen übernimmt.
dazu kommen herausforderungen an rekursive schleifen, weil die textbox nämlich in einer groupbox des gradientpanels der registerseite x des tabcontrols des panels2 des splitterpanels des armen formulares liegen kann.... 😉
hallo heimi,
wenn es um arbeitszeiten geht: ich habe einen solchen auftrag seinerzeit hauptsächlich über die datenbank gelöst.
[beginn] und [ende] sind hier datetime spalten mit vollständigem zeitstempel.
eine berechnete spalte [Dauer] rechnet für mich die arbeitszeit wie folgt aus:
case
when ([typ] = 0) then (datediff(minute,[Beginn],[Ende]) / convert(float,(-60)))
when ([typ] = 1) then (datediff(minute,[Beginn],[Ende]) / convert(float,60))
when ([typ] > 1) then 0
end
mit:
0 - Pause; 1 - Arbeitszeit;
das problem ist u.a., dass jemand ja mehrere pausen machen kann, daher sind alle pausen als negative arbeitszeiteinträge pro tag hinterlegt.
am monatsende lässt du dann bspw. mit einer stored procedure die arbeitszeiten des monats nach mitarbeiter gruppiert summieren.
ein weiteres problem war (und ist ggf. für dich), dass das system einem arbeitstag automatisch eine pause von 30 minuten hinzufügen muss, wenn der mitarbeiter keine gemacht hat aber länger als 6 std. gearbeitet hat (rechtliche vorgabe).
im programm brauchst du also nur die wirklichen beginn- und endezeiten.
wie bernd schon andeutet, hast du dann die timespan als zeitspannen für arbeitszeiten und pausenzeiten.
gruß
ron
hi herbivore,
(bool)(i < Convert.ToInt16(txtLoop.Text)) ist eine merkwürdige Konstruktion stimmt, hatte beim testen auf die schnelle hier einen fehler vermutet, aber lag ja nicht daran... 😉
Besser entweder TextBoxes.Count stimmt !
oder gleich eine foreach-Schleife verwenden. iss net so gut weil dann innerhalb der schleife der index nicht bekannt ist: die textbox weiss ja nichts von ihrer position, oder?
gruß
ron
hey heimi,
warum willst du sie denn unbedingt trennen?
anyway, im günstigsten fall brauchst du die werte der beiden formularfelder nur zu addieren, weil datumswerte intern als gebrochene zahlen codiert sind: ganzzahliger anteil = tag, gebrochener teil = uhrzeit.
dann gibt es ein verabredetes startdatum, bei c# ist die zahl 0 der 1.1.0001, 00:00:00 Uhr
von der sql seite kommend kannst du sie trennen über
convert(varchar, Geburtsdatum, 104)
dabei ist 104 deutsche formatierung mit jahreszahl etc.
guggsdu unter cast/convert der sql doku,
aber wie gesagt, seit datetimepicker und maskedtextbox sehe ich denn sinn nicht so ganz...
gruß
ron
hi folks, wie wäre es mit einer Liste?
public Form1()
{
InitializeComponent();
SuspendLayout();
for (int i = 0; i < 20; i++)
{
TextBox tb = new TextBox();
tb.Size = new Size(100, 20);
tb.Location = new Point(10, i * (tb.Height +3));
TextBoxes.Add(tb);
this.Controls.Add(tb);
}
ResumeLayout(true);
}
Mit folgender Schleife kann dann die Sichtbarkeit gesteuert werden:
for (int i = 0; i < 20; i++)
{
TextBoxes[i].Visible = (bool)(i < Convert.ToInt16(txtLoop.Text));
}
Ausserdem kannst du nun über die Indizierung eine beliebige Textboxansprechen, ohne ihren "Namen" zu kennen...
und was heisst hier spät... 😉