Laden...
Avatar #avatar-1693.jpg
citizen.ron myCSharp.de - Member
Selbst. Software-Architekt Frankfurt / Main Dabei seit 23.07.2005 432 Beiträge
Benutzerbeschreibung

Forenbeiträge von citizen.ron Ingesamt 432 Beiträge

21.11.2005 - 19:13 Uhr

hi huskjet,

wenn wir davon ausgehen, dass du weisst, wie und wann du auf das ereignis der knotenselektion reagieren kannst, wäre ein ansatz, bspw. die knoten von TreeNode zu erben und um die Eigenschaft RecordID zu erweitern. auf diese weise schaffst du schonmal eine informelle verbindung zwischen TreeView und DataGridView. sowas mache ich auch.

der insert in das treeview ist dann auch kein problem, da du ja stets nur EINEN neuen datensatz bearbeiten kannst und der ist eben der neue knoten. nach umbenennen des knotens durch den benutzer (falls du das überhaupt erlauben willst) kannst du mit diesem namen ja z.b. schon arbeiten: den neuen datensatz erzeugen, den knotennamen in eine der spalten übernehmen, ggf. schonmal speichern und die recordid gewinnen um sie dem neuen knoten zuzuweisen...

alles ganz einfach, oder?

wie herbivore schon sagt: du weisst ja was du willst, so just go 4 it 😉

hth, ron

21.11.2005 - 19:05 Uhr

hi marcel,

ich schlag mal ganz verwegen vor, dass du am besten einen sql server 2005 nimmst, das update in eine stored procedure packst, die du natürlich unter c# geschrieben und eingebunden hast und die ganz nebenbei noch die sache mit dem prozessbalken mit erledigt.... 😉

21.11.2005 - 19:02 Uhr

hi folks,

ich krieg´s nicht hin, ein formular, das ich als control in einem panel eines anderen forms darstelle, mit einem schatten bzw mit leichter transparenz zu versehen.

anscheinend ist die eigenschaft Opacity wirkungslos, wenn das formular ein control ist, also nicht toplevel?
kann man da was dagegen tun?

danke vorab
ron

21.11.2005 - 07:30 Uhr

hi fzelle,

danke, über Moshe Plotkin war ich dann auch gefallen, aber ich wollte erstmal was schnelles ohne Bearbeitungsfunktion...

gruß
ron

20.11.2005 - 13:29 Uhr

hurra, soweit so gut

für alle, die´s selber mal ausprobieren wollen, hier ein bisschen code:

das endlosformular braucht z.b. sowas:
(das prinzip basiert darauf, dass der zugrundeliegende spaltenname der datarow im tag des labels abgelegt ist)

 public partial class frmContinuous : Form
 {
    public event SelectionChanged  SelectionChanged;
    
    private DataRow      dataRow;
    private int          index;

    public frmContinuous(DataRow record, int controlIndex)
    {
       InitializeComponent();
       dataRow = record;
       TopLevel = false;
       //Dock = DockStyle.Top;  nur nötig, wenn übergeordneter container ein panel ist
       index = controlIndex;
       lblTitle.Text = dataRow["Title"].ToString();
       foreach (Control ctrl in pnlData.Controls)
       {
          try {ctrl.Text = dataRow[ctrl.Tag.ToString()].ToString();}
          catch {}
       }
   }

    public void Deselect()
    {
       pnlHeader.BackColor = Color.Gainsboro;
       lblTitle.ForeColor = Color.Black;
       pnlData.BackColor = Color.White;
    }

    private void eh_FormSelected(object sender, EventArgs e)
    {//Eventhandler des Click-Ereignisses der Header-Elemente:
    // Farbattribute setzen:
       pnlHeader.BackColor = Color.RoyalBlue;
       lblTitle.ForeColor = Color.White;
       pnlData.BackColor = Color.AliceBlue;
    // EventHandler im Mutterformular abrufen, um aktuelle Selektion zu aktualisieren
       if (SelectionChanged != null) SelectionChanged(index);
    }
 }

das aufrufende formular braucht z.b. das hier:


   #region Delegates
      public delegate void SelectionChanged(int controlIndex);
   #endregion
   private int    currentSelection = -1;

   private void btnPopulateList_Click(object sender, EventArgs e)
    {
       DataTable dt = // hier der passende code für datenbeschaffung...
       
       foreach (DataRow record in dt.Rows)
       {
          frmContinuous frm = new frmContinuous(record, myFloatingLayoutPanel.Controls.Count);
          myFloatingLayoutPanel.Controls.Add(frm);
          frm.SelectionChanged += new SelectionChanged(eh_SelectionChanged);
          frm.Show();
       }
    }

    void eh_SelectionChanged(int controlIndex)
    {
       if ((currentSelection >= 0) && (currentSelection != controlIndex)) try
       {
          frmContinuous frm = (frmContinuous)myFloatingLayoutPanel.Controls[currentSelection];
          frm.Deselect();
          frm = null;
       }
       catch {}
       currentSelection = controlIndex;
    }

der delegate und sein eventhandler sorgen hier nur dafür, dass das übergeordnete formular "weiss", welches element im endlosformular-container gerade ausgewählt ist. auf diese weise kann es auch die methode Deselect() aufrufen, um für die vorige Selektion die farben wieder zurückzusetzen.

der anhang zeigt das ergebnis

gruß
ron

ps @herbivore:
wie du siehst, habe ich´s mit dem flowlayoutpanel ebenfalls hingekriegt, danke; panel klappt problemlos;

ps2 @ herbivore:
wenn man sich deine uhrzeiten so ansieht, kommst du auch nicht vom pc weg, oder?
😉

20.11.2005 - 11:04 Uhr

hallo zusammen,

ich würde gerne das konzept der endlosformulare aus access in c# realisieren.
und zwar erstmal read-only; ich halte es nicht für sinnvoll, daten in gittern oder endlosformularen auch wirklich zu bearbeiten. also als modell können wir uns da die visitenkartenansicht von outlook für adressen vorstellen (ohne in-place bearbeitung), das trifft meine zielvorstellung am ehesten..

konzeptionell würde ich da jetzt ansetzen mit einem formularentwurf für ein bestimmtes datenobjekt (also: layout und felder richten sich nach den spalten des datensatzes), das formular erhält im konstruktor eine datarow, welche die dateninhalte enthält.

zur laufzeit wird das formular dann n-mal mit einem jeweils anderen datensatz (datarow) instanziert und in, tja, wohinein eigentlich "gesubformt"?

panels? ok, können laufbalken 😄, wär das was?

listviews? kann man denn eine form zu einem listviewitem casten? ist aber zu unflexibel oder?

ist der ansatz so brauchbar?

wie wär´s mit TableLayoutPanel?
oder was macht eigentlich ein FloatingLayoutPanel?

ein paar gedanken von euch hierzu wären hilfreich...

danke

ron

19.11.2005 - 09:09 Uhr

tja, da gibt es jetzt schon so viele artikel dazu und trotzdem tauchen immer wieder neue probleme auf.

beim versuch meine ausgabesprache zur laufzeit umzuschalten, kriege ich folgenden fehler (VS 2005!):

Could not find any resources appropriate for the specified culture or the neutral culture. Make sure "myApp.resources" was correctly embedded or linked into assembly "myApp" at compile time, or that all the satellite assemblies required are loadable and fully signed.

meine vorgehensweise ist:1.Anlegen eines Formulares, Localizable = true und in den jeweils anderen Sprachen das text-property neu eingeben 1.damit auch fehlermeldungen u.ä. übersetzt werden können: strings mit gleichen bezeichnern in verschiedene resource dateien auf projektebene anlegen, also: myApp.en-US.resx, myApp.fr-FR.resx usw. 1.Jetzt kommt schon das erste problem: muss das property BuildAction für die resource dateien auf [Embedded resource] stehen oder [Compile] oder [Content]? Mit der Einstellung [Embedded Resource] erhalte ich jedenfalls in einem Verzeichnis Baum innerhalb des projekts meine sprachen; das deckt sich immerhin mit den infos aus allerlei forumsquellen hier... 1.jetzt implementiere ich noch eine umschaltung der sprache in unten genannter form:

ResourceManager resMgr = new ResourceManager("myApp", Assembly.GetExecutingAssembly());
msg = resMgr.GetString("err_Test");
MessageBox.Show(msg);
CultureInfo ci = new CultureInfo("en-US");
resMgr.GetResourceSet(ci, false, true);
msg = resMgr.GetString("err_Test", ci);
MessageBox.Show(msg);

die erste ausgabe sollte die default-sprache zeigen, die zweite mbox sollte den englischen text zeigen. aber schon der erste GetString-Befehl kracht mit obiger fehlermeldung. es gibt ja auch tatsächlich keine "myApp.resources", sondern nur eine "myApp.resources.dll" im jeweiligen sprachpfad...

was hab ich jetzt hier falsch gemacht?

thanx, ron

18.11.2005 - 11:10 Uhr

hallo bini

warum typisierte datasets "schlecht" sind, hat bini ja schon hinreichend erklärt... 😉

Kannst Du Deine DLL-Registrierung in der DB noch ein bißchen ausführlicher beschreiben, ich kann mir noch nicht recht vorstellen, wie das funktioniert. In der DB stehen nur die Namen der DLLs?

nun, ich habe letztlich alle dll´s in einer tabellenspalte namentlich genannt, ausserdem die klasse, die innerhalb der dll die implementierung eines interfaces darstellt. auf diese weise kann sich die anwendung darauf verlassen, dass die instanz des objekts garantiert eine implementierung sagen wir des interface "IAnsicht" ist.

der pfad der dlls wird über config-datei oder registry gesteuert und da liegen die dll´s dann physisch drin.

darüberhinaus steuern weitere tabellen, welche dll für welchen benutzer zugänglich ist, ggf. seine weiteren rechte daran, natürlich kann man auch noch hinterlegen, ob sie seitens des kunden lizenziert ist usw.

nachstehend ein bissi code der klasse, die für das laden und anzeigen der dll aus den angaben der tabelle verantwortlich ist:


  
      private IAnsicht PlugIn;      // Variable, die eine Instanz der in der DLL definierten Klasse aufnimmt

  // View ist die Klasse, die für das Laden der DLL aus der Tabelle zuständig ist
  // In ihrem Konstruktor erhält sie den für sie zuständigen Datensatz aus der Tabelle.
  // Der Pfad der DLLs wird über config-Datei oder registry gesteuert und kommt ebenfalls von aussen
      public View(DataRow record, string libPath, Panel targetPanel)
      {
         viewRecord  = record;
         assembly    = null;
         PlugIn      = null;
         form        = null;
         DLLPath     = libPath;
         viewPanel   = targetPanel;
         _Label            = viewRecord["Label"].ToString();
         _Action           = (eViewAction)viewRecord["Action"];
         assemblyFileName  = viewRecord["AssemblyFileName"].ToString();
         plugInClassName   = viewRecord["ClassName"].ToString();
         _IndexKey         = viewRecord["ControlName"].ToString();
         _Flags            = (eViewFlags)viewRecord["Flags"];
         if (viewRecord["Picture"] != DBNull.Value) try
         {
            MemoryStream mStream = new MemoryStream((Byte[])@viewRecord["Picture"]);  
            _Picture = new Bitmap(mStream, true);
            mStream.Close();
         }
         catch (Exception exception)
         {
            Messenger.Process(exception, "Error reading image stream of view '" + _Label + "':");
         }
      }

      private bool LoadAssembly()
      {//Load the assembly
         bool result = false;

         try
         {
            if (assembly == null) assembly = Assembly.LoadFrom(DLLPath + assemblyFileName + ".dll");
            Messenger.Process("Loaded assembly file " + assembly.FullName);
            if (PlugIn   == null) PlugIn   = (IAnsicht )assembly.CreateInstance(plugInClassName);
            Messenger.Process("Instantiated class " + plugInClassName);
            result = (PlugIn != null);
         }
         catch {}
         return result;
      }

      public Form ShowWindow(Form parentForm)
      {
         Form result = null;
         if (LoadAssembly()) 
         {
            IAnsicht childWindow = (IAnsicht)assembly.CreateInstance(plugInClassName);
            childWindow.ShowWindow(parentForm);
         }
         return result;
      }

hth, ron

17.11.2005 - 14:05 Uhr

danke friedel,
und grosses dank an euch alle, die mitgeholfen haben.

erstens habe ich wieder ne menge gelernt und zweitens klappts auch noch... =)

für die interessierten unter euch, nachstehend der belohnungscode:
eine checkbox, die tooltips unterstützt und die auswahl eines labels im gleichen container erlaubt, in dem ein hilfetext angezeigt wird, sobald der benutzer die checkbox fokussiert.

das ganze wird natürlich erst richtig sinnvoll, wenn mann alle labels aller übergeordneten container im eigenschaftenfenster anbietet, aber daran sitze ich heute nachmittag noch... 🤔

using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Drawing;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace CCL
{

   public class FlagChecker : System.Windows.Forms.CheckBox
   {
   #region Members
      ToolTip  toolTip;
   #endregion

   #region Properties
      /// <summary>
      /// Gets or sets the tooltip text for this control
      /// </summary>
      private string _ToolTipText;
      public  string  ToolTipText
      {
         get { return _ToolTipText; }
         set 
         { 
            _ToolTipText = value; 
            if (StatusMsgText == null) StatusMsgText = value;
            if (toolTip != null) toolTip.SetToolTip(this, _ToolTipText);
         }
      }

      /// <summary>
      /// Gets or sets the message text displayed in the hint label object
      /// </summary>
      private string _StatusMsgText;
      public  string  StatusMsgText
      {
         get { return _StatusMsgText; }
         set 
         { 
            _StatusMsgText = value; 
            if (ToolTipText == null) ToolTipText = value;
         }
      }


      /// <summary>
      /// Gets or sets the hint label object where status messages are displayed
      /// </summary>
      private Label _StatusMsgLabel;
      [TypeConverter(typeof(StatusMsgLabelConverter)), Category("Details")]
      public string StatusMsgLabel
      {
         get { return (_StatusMsgLabel != null) ? _StatusMsgLabel.Name : null; }
         set { if (Parent != null) _StatusMsgLabel = (Label)Parent.Controls[value]; }
      }

   #endregion

   internal class StatusMsgLabelConverter : System.ComponentModel.StringConverter
   {
      private FlagChecker  parent;

      public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
      {
         return true;
      }
      public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
      {
         ArrayList lblNames = new ArrayList();
         if (context != null) try
         {
            this.parent = (FlagChecker)context.Instance;
            foreach(Control ctrl in parent.Parent.Controls)
            {
               if (ctrl.GetType().ToString() == "System.Windows.Forms.Label")
               {
                  lblNames.Add(ctrl.Name);
               }
            }
         }
         catch
         {
            lblNames.Add("Keine Instanz verfügbar");
         }
         StandardValuesCollection svc = new StandardValuesCollection(lblNames.ToArray());
         return svc;
      }
   }

   #region Constructor(s)
      public FlagChecker() : base()
      {
         this.Enter  += new EventHandler(this.Internal_Enter);
         this.Leave  += new EventHandler(this.Internal_Leave);
      }

   #endregion

   #region Internal Events
      protected void Internal_Enter(object sender, EventArgs e)
      {
         if (_StatusMsgLabel != null) _StatusMsgLabel.Text = _StatusMsgText;
      }
      protected void Internal_Leave(object sender, EventArgs e)
      {
         if (_StatusMsgLabel != null) _StatusMsgLabel.Text = "";
      }
   #endregion
   }
}
17.11.2005 - 12:18 Uhr

hi leute,

danke, danke, danke!

bin schon ein ganzes stück weiter.

jetzt habe ich das problem, von der internen klasse des StringConverters auf die übergeordnete klasse zugreifen zu müssen. wisst ihr, wie das geht?

 public class FlagChecker : System.Windows.Forms.CheckBox
 {
    /// <summary>
    /// Gets or sets the hint label object where status messages are displayed
    /// </summary>
    private string _HintLabel;
    [TypeConverter(typeof(HintLabelConverter)), Category("Details")]
    public string HintLabel
    {
       get { return _HintLabel; }
       set { _HintLabel = value; }
    }

    internal class HintLabelConverter : System.ComponentModel.StringConverter
    {
       public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
       {
          return true;
       }
       public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
       {
          string[] ar = new string[]{"Nummer 1", "Nummer 2", "Nummer 3"};
          //stattdessen soll hier ja eine arraybildung aller Labels aller Container gebildet werden, 
          // in die die umgebenden Klasse FlagChecker eingebettet wurde.
          // Also: wie kann ich von hier aus auf die Elemente der umgebenden Klasse FlagChecker drauf?
          StandardValuesCollection svc = new StandardValuesCollection(ar);
          return svc;
       }
    }
 }

thanx, ron

16.11.2005 - 16:03 Uhr

hi leute,

danke für die verweise.
ich komme leider damit nicht weiter: die beispiele im msdn magazine, die ich gefunden habe, enthalten keine derartigen properties; den webcast kann ich mir nicht ansehen und die msdn online hilfe ist zu umfassend/allgemein.

also: wenn einer von euch dann vielleicht doch ein code beispiel hätte... 😉

ron

16.11.2005 - 14:05 Uhr

hi folks,

ich möchte ein eigenes steuerelement erstellen, das von textbox abgeleitet ist.
sagen wir, ich möchte als zusätzliche eigenschaft ein property namens HintLabel vom Typ Label drinhaben.

Zur entwurfszeit später möchte ich nun meine textbox in einem formular einbetten und die eigenschaft HintLabel soll mir im eigenschaftenfenster in einer aufklappbaren liste alle steuerelemente aller übergeordneten container-elemente zur auswahl anbieten, die vom typ Label sind.

klar ist mir, wann und wie ich alle Label-objekte übergeordneter steuerelemente (panels, form, etc.) ermittle; ich würde das in den konstruktor packen, weil zu dieser zeit die textbox ja schon weiss in welchem container sie eingebettet wurde.

**unklar **ist mir, wie ich bei der implementierung meiner textbox dafür sorge, dass das property HintLabel als liste dargestellt wird (und nicht einfach als texteingabefeld) und wie die elemente in diese liste hineinkommen.

thanx vorab

ron

16.11.2005 - 08:44 Uhr

oooh f _ _ _ !

naja, zum glück werden hier auch stümper und dilettanten geholfen... 8)

thanx noodles

16.11.2005 - 08:19 Uhr

hi noodles,

danke, dein letzter hinweis hat mein problem gelöst.

Warum leitest Du eigentlich nicht direkt von CheckBox ab?

wenn ich direkt von checkbox ableite und das in meine dll kompiliere, sagt mir die ide beim versuch sie für die toolbox zu registrieren: "There are no elements in 'bla.dll' that can be placed in the toolbox."

vielleicht ist an der abgeleiteten implementierung irgendwas falsch:?

using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Text;

namespace CCL
{
   class OptionFlag : CheckBox
   {
      /// <summary>
      /// Gets or sets the flag value
      /// </summary>
      [Browsable(true)]
      [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] 
      private int _FlagValue;
      public  int  FlagValue
      {
         get { return _FlagValue; }
         set { _FlagValue = value; }
      }

   }
}

muss ich noch mehr machen...???

(ähem, ist halt meine erste eigene komponente...)

15.11.2005 - 18:31 Uhr

hi herby

leider hilft das nix, so hatte ich es ja erst und hab´in meiner verzweiflung danach überhaupt erst _Text zusätzlich als member eingeführt.

das komische ist, dass der designer keine codezeile für den text erzeugt, nachstehend das, was er macht:

this.optionChecker1.FlagValue = 0;
this.optionChecker1.Location = new System.Drawing.Point(128, 149);
this.optionChecker1.Name = "optionChecker1";
this.optionChecker1.Size = new System.Drawing.Size(117, 21);
this.optionChecker1.TabIndex = 8;
this.optionChecker1.ToolTipText = null;

wie man sieht, sind meine anderen eigenen properties alle vorhanden: ToolTipText und FlagValue.

und Text?
gute nacht marie! X(

15.11.2005 - 18:15 Uhr

hallo zusammen,

ich komm nochmal auf das thema zurück.

ich möchte eine erweiterte checkbox erstellen.
offensichtlich muss ich dabei von UserControl erben und im Designer eine checkbox in mein control "hineinlegen".

(beim erben kriege ich nämlich seitens der IDE beim einbinden meiner dll in die toolbox gesagt, es sei keine komponente für die steuerelemente-toolbox in der bibliothek vorhanden)

ok, wenn ich das aber mache, kann ich anscheinend das property Text nicht vernünftig zum einsatz bringen: durch änderung des properties im eigenschaftenfenster soll natürlich auch der anzeigetext der eingebetteten checkbox verändert werden, also würde die property implementierung doch wie folgt aussehen müssen, oder❔

     
/// <summary>
/// Gets or sets the text for the checkbox
/// </summary>
private string _Text;
[Browsable(true)] 
public override string Text
{
   get { return _Text; }
   set 
   { 
      _Text = value;
      icCheckbox.Text = value;
   }
}

das phänomen ist nun aber, dass ich zwar die Eigenschaft Text im Eigenschaftenfenster angezeigt bekomme, deren Änderung aber keine Auswirkung auf den vom designer generierten code hat: ich sehe zwar am bildschirm, dass sich der anzeigetext der checkbox geändert hat (weil der setter das ja mit erledigt hat) aber sobald ich die datei speichere und schliesse und wieder öffne, ist aber der text der checkbox verloren gegangen.

hä?

hilfe!

thanx,
ron

15.11.2005 - 15:37 Uhr

...und wie verpass ich jetzt jeder einzelnen komponente in meiner komponentenbibliothek ein eigenes symbol, das dann im steuerelementefenster der ide verwendet wird?

15.11.2005 - 15:31 Uhr

wusste doch da war was, hab aber mein c# buch gerade meinem azubi geliehen...

thanx noodles, hab dich lieb 8)

15.11.2005 - 15:19 Uhr

hi folks,

ich versuche gerade (offengestanden mein erstes) UserControl zu erstellen.

im grunde ist es eine erweiterung einer Checkbox.

klappt auch alles, nur dass ich das Property Text ums verrecken nicht im Eigenschaftenfenster angezeigt bekomme.
da es geerbt ist von UserControl, muss ich es überschreiben oder als new deklarieren; ist aber egal, was ich mache: ich krieg es nicht angezeigt.

meine eigenen properties funktionieren dagegen tadellos.

gibt´s da etwas, wovon ich nix weiss?

hier der code auszugsweise:

public partial class Checkbox : UserControl
{
   #region Members
      ToolTip  toolTip;
   #endregion

   #region Properties
      /// <summary>
      /// Gets or sets the tooltip text for this control
      /// </summary>
      private string _ToolTipText;
      public  string  ToolTipText
      {
         get { return _ToolTipText; }
         set 
         { 
            _ToolTipText = value; 
            toolTip.SetToolTip(icCheckbox, _ToolTipText);
         }
      }

      /// <summary>
      /// Gets or sets the text for the checkbox
      /// </summary>
      public override string Text
      {
         get { return icCheckbox.Text; }
         set { icCheckbox.Text = value; }
      }

      /// <summary>
      /// Gets or sets the flag value
      /// </summary>
      private int _FlagValue;
      public int FlagValue
      {
         get { return _FlagValue; }
         set { _FlagValue = value; }
      }

   #endregion

danke vorab
ron

15.11.2005 - 09:12 Uhr

hey flippo,

bin mir nicht ganz sicher, aber könnte es sein dass ein commandbuilder nicht auf wildcards steht ("select * from ...") ?

hast du´s mal mit einer expliziten spaltenangabe im select versucht?

und: wie sehen im debugger die update- und delete- command objekte nach aufruf des commandbuilders aus?
sind die != null?

hth

ron

13.11.2005 - 10:15 Uhr

hurrraaaaaaa,

got the sh..!

also, fassen wir das glückliche ergebnis nochmal zusammen:
wer graphische objekte in ein sql tabellenfeld vom typ [image] ablegen will, sollte das am besten mit dem commandline tool bii.exe oder mit eigenen stored procedures tun, keinesfalls aber mit Access, denn Access schreibt einen zusätzlichen OLE header in das image.

will man das image anschliessend mit streams auslesen, MUSS man einen offset im stream definieren. der himmel weiss (und billy), ob das aber zukünftig auch immer 78 byte bleiben, also: finger weg davon! 😉

c u with the next problem
ron

13.11.2005 - 09:46 Uhr

yassu kostas, guten morgen alle anderen!

hier noch eine ergänzung zu meiner architektur:
die dll´s sind alle implementierungen des gleichen interfaces, in meinem fall eine ICRMView. Hierdurch trage ich dem von vielen hier propagierten "Microkernel" insofern rechnung, als ich mit interfaces arbeite. ich habe allerdings auf eine "factory-dll" verzichtet, die selbst wieder nur die instanzen erstellt. meine GUI, sprich: desktopformular, weiss, dass alle DLL´s ICRMView-Implementierungen sind.

Wie ist es eigentlich bei DLLs, wenn ein User die Anwendung gestartet hat,
sind doch die benutzte Dlls offen und ...

Die dll´s sind alle lokal installiert und werden per publishing verteilt. eine dll ist daher immer nur einmal geladen. minimum-versionsanforderungen lassen sich über die funktionalität des frameworks lösen.

Typisiere Dataseds würde ich gerne aus zwei Gründen verwenden:

  1. Tippfehler...

Nicht grund genug ! 😜

  1. Die Datenbindung zur Textboxes, Checkboxes, ebenso die einzelnen Felder in den Grids...

Das grid (in .net 2.0 jedenfalls) ermittelt die spaltenstruktur automatisch. sollten gggf. spalten der gesamtstruktur einer abfrage/tabelle nicht sichtbar sein, lässt sich das wiederum über einen mechanismus (z.B. in meinem fall des View-interfaces und des sql wrappers) lösen.

steuerelemente der detailansichten müssen auch nicht über code angebunden werden, denn die databindings-properties (in vs 2005) erwarten nicht, dass die datenanbindung zur entwurfszeit tatsächlich vorliegt, d.h. ich kann ein control durchaus auf [myDataset].[MyTable].[myColumn] verweisen, ohne dass es das zur entwurfszeit schon gäbe. das control interessiert sich im schlimmsten fall ja nur für die BindingSource, und die kann ich zur laufzeit ja immer noch auf die richtige zieltabelle im untypisierten dataset umbiegen, kostet nen einzeiler =)

...Datensicht in einer DLL zu packen. Doch warum würde ich gerne wissen? ...

die vorteile sind bei der größenordnung deser projekte einerseits eine schrittweise modulare inbetriebnahme, weil ich nach und nach (z.b. abteilungsweise) prozesse automatisieren und die zugehörigen module ausliefern kann ohne die installation auch nur anzufassen; neue dlls werden in einer tabelle der DB eingetragen und sind dann verfügbar. aus dem gleichen grund erziele ich eine bessere wartbarkeit.

hth, ron

12.11.2005 - 18:12 Uhr

hey leute, seht euch das mal an:

http://www.eggheadcafe.com/articles/20050911.asp

der autor schreibt:

In this particular case, Images in the Northwind Employees table were designed from MS Access, which expects a 78 byte OLE header, which we'll strip off. We write the rest of the array into our MemoryStream.

das problem scheint dann aufzutauchen, wenn man access benutzt, um das bild in das image feld abzulegen; daher kamen auch meine unterschiedlichen byte-array längen.

ich werde jetzt mal versuchen, die bitmap aus einer datei über eine stored procedure in die tabelle zu schiessen und sie dann wieder auszulesen.

melde mich morgen vormittag mit den neuigkeiten, jetzt muss ich erstmal ein paar caipies trinken gehen... 😉

c u, ron

12.11.2005 - 17:13 Uhr

hi herbivore,

habe jetzt die bitmap aus dem stream ausgelesen und in eine datei gespeichert.

         DataRow record = dsCCMDEV.Tables[0].Rows[4];
         MemoryStream mStream = new MemoryStream((byte[])record["Picture"]);
         FileStream fs = new FileStream("C:\\temp\\kannweg.bmp", FileMode.CreateNew);
         byte[] mByte = new byte[mStream.Length];
         fs.Write(mByte, 0, mByte.Length);
         fs.Flush();
         fs.Close();

und schau mal da: die datei ist auch nicht brauchbar...

wieso wird´s dann in der picturebox über die databindings angezeigt?
wieso wird es aus der tabelle in access angezeigt?
wieso ist es in office aus der tabelle als gültiges ole-objekt in paint bearbeitbar?

????

nix kapisch

12.11.2005 - 16:58 Uhr

hi herbivore,

aber das habe ich doch alles schon gemacht (siehe meine früheren posts).

und wenn doch die datengebundene picturebox über databindings angebunden das bild anzeigen kann, heisst das doch: technisch ist die information sauber.

das einzige, was anders ist, ist der technische weg von der datenbank in die picturebox: machen es die databindings klappts, mach ich es per stream, kracht´s.

fazit: entweder ist es einfach nicht möglich, image felder mit streams auszulesen und implizit als bitmap zu interpretieren, oder da iss halt n bug

12.11.2005 - 16:16 Uhr

hi luetter und die anderen,

also nochmal: ich habe keine access datenbank, sondern eine sql server tabelle mit datentyp [image], genau wie bei luetter.

ich habe access nur benutzt, um das bild in die tabelle reinzukriegen und ich kriegs da auch wieder heraus.

ich kann das bild mit einer datengebundenen picturebox in c# auch anzeigen. das bedeutet das bild ist technisch absolut ok.

wenn luetter und ich aber auf das bild per stream zugreifen, kracht es mit der exception "parameter not valid" bzw. auf deutsch "Ungültiger Parameter".

da ist doch was oberfaul, oder "new Bitmap(..." ist im falle sql server und image einfach nicht der richtige weg, ich weiss nur leider keinen anderen 🙁

(deperate) ron

12.11.2005 - 09:39 Uhr

hi kostas,

ich habe zwei projekte deiner dimension, die ich in den nächsten monaten von access frontend auf c# portieren werde. die daten liegen auf einem sql server 2000. als ich mit c# angefangen habe, waren meine fragen im grunde die gleichen wie deine; ich habe mich für nachstehendes konzept entschieden und fahre damit gut, daher hier in kürze die architektur:
1.ich packe ca. 60-80 % der geschäftslogik in stored procedures, udf´s und trigger (das habe ich schon immer so gemacht, auch mit dem access frontend) 1.eine selbstgeschriebene singleton wrapper klasse übernimmt meine aufrufe von SP´s und UDF´s, in dem sinne, dass ich mich bei aufruf nicht mehr um die namen der parameter kümmern muss 1.Der wrapper ist der einzige kerl in meiner anwendung, der ein dataset kennt und das ist untypisiert; für meine projekte habe ich nämlich keinen grund gefunden, jemals ein typisiertes DataSet zu verwenden (vielleicht kann mir jemand hier mal einen nennen...?) 1.mein desktop ist eine leere hülle, die alle datenansichten nur aus DLL´s lädt 1.jede datenansicht ist eine DLL; der verbleibende teil evtl. geschäftslogik kommt hier zum liegen und alle DLL´s benutzen den singleton wrapper

was mich hierhin gebracht hat, war folgender ansatz:
Änderungen am Datenmodell betreffen immer einen teil der GUI, weil felder auch gefüllt/gepflegt werden wollen. habe ich jetzt also eine änderung, passe ich nur die zuständige DLL an, kompiliere sie und liefere sie neu aus.
die anwendung muss nicht angefasst werden. selbst wenn ganze tabellen und geschäftsprozesse dazukommen, weil alle dll´s namentlich in einer eigenen tabelle der DB registriert sind. die anwendung lädt eben einfach alles bei bedarf.

hth, ron

**PS zu deinem beispielcode **(public void ReadWithPK(enumTbl id...)...):
etwas ähnliches habe ich auch gemacht, allerdings ebenfalls auf SP Basis. in meinen datenbanken heissen ALLE primary keys grundsätzlich [RecordID].
Mit folgender SP kann ich jetzt beispielsweise in jeder tabelle einen gewünschten datensatz löschen:

CREATE PROCEDURE udp_d_Record @tableName varchar(40), @recordID int
AS
declare @sql varchar(400)
@sql = 'DELETE FROM [' + @tableName + '] where RecordID = ' + convert(varchar, @recordID)
exec @sql

PS 2: ellinas isse?

12.11.2005 - 09:11 Uhr

hey nasgul,

vermutlich stört den compiler an currentFolder, dass die variablendeklaration in meinem code ausschnitt verlorenging (ich hab dir ja leider nicht meine komplette "wie integriere ich alles was outlook kann in meine anwendung"-bibliothek geschickt... 😛)

currentFolder muss als MAPIFolder deklariert werden:

...
#region Members
      private Outlook.MAPIFolder          olFldPublicRoot;     // Public folders root
      private Outlook.MAPIFolder          olFldPrivateRoot;    // Personal folders root
      private Outlook.NameSpace           olMAPI;              // Session namesapce
      private Outlook.ApplicationClass    olApp;               // Session outlook application
      private Outlook.MAPIFolder          currentFolder  
#endregion
...

hth, ron

12.11.2005 - 09:02 Uhr

hey bogo

die hinweise von lastgentleman sind absolut korrekt und vor allem dann sinnvoll, wenn du die erweiterte information an zentralisierter stelle ablegen willst.

solltest du wirklich die "Dokumenteigenschaften" erweitern wollen, kannst du das auch über ThisDocument.CustomDocumentProperties, ein property das auch über die vsto erreichbar sein sollte.

Kann man dafür eventuell eine spezial *.dot erstellen die diese Felder auch vorgeben?

klar, du brauchst dort dann nur das ereignis New() der Vorlage abzufangen, um deine ergänzenden Eigenschaften zu erzeugen; dieses ereignis findet immer dann statt, wenn auf basis der vorlage ein neues dokument hergestellt wird

hth, ron

10.11.2005 - 07:37 Uhr

😦hi herbivore,

wie erzeugst du (Byte[])record["Picture"]

record ist vom typ datarow.
die längen sind gleich. der read-befehl ist auch hier nur im beispiel drin, um zu zeigen, dass ich die längen und inhalte verglichen habe, weil ich im debugger dann wenigstens den inhalt des streams über mByte[] einsehen (und mit dem inhalt von fStream, dem aus der datei) vergleichen kann.

im grunde würde ja eigentlich reichen:

MemoryStream mStream = new MemoryStream((Byte[])record["Picture"]);  
Bitmap picture = new Bitmap(mStream); 
mStream.Close(); 

aber das kracht halt in der picture = ...-zuweisung mit "Parameter not valid", obwohl die Bitmap im tabellenfeld gültig ist und z.B. von Access auch als "Bitmap" ausgewiesen und über das Kontextmenü als Paint-Objekt angezeigt wird.

mir gehen die ideen aus; schließlich ist der obige dreizeiler das, was auch in allen beispielen, u.a. auch hier im forum, genannt wird... 🙁

09.11.2005 - 17:24 Uhr

hi nasgul,

nachstehend ein code beispiel

du brauchst meines wissens nach die vsto (visual studio tools für office).

nach deren einbindung kannst du dann nachstehendes realisieren:



using Outlook = Microsoft.Office.Interop.Outlook;

#region Members
      private Outlook.MAPIFolder          olFldPublicRoot;     // Public folders root
      private Outlook.MAPIFolder          olFldPrivateRoot;    // Personal folders root
      private Outlook.NameSpace           olMAPI;              // Session namesapce
      private Outlook.ApplicationClass    olApp;               // Session outlook application
#endregion


private void InitOutlook()
{//Init Outlook Information Store
   try
   {
      olApp    = new Outlook.ApplicationClass();
      olMAPI   = olApp.GetNamespace("MAPI");
      olFldPublicRoot   = olMAPI.Folders[1];
      olFldPrivateRoot  = olMAPI.Folders[2];
      currentFolder = olMAPI.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);      
   }
   catch {}
}

private void MachMirNTermin()
{
   Outlook.AppointmentItem ai;
   ai = (Outlook.AppointmentItem)currentFolder.Items.Add(Outlook.OlItemType.olAppointmentItem);
   ai.Start = DateTime.Now;
   ai.Subject = "kannweg";
   ai.End = DateTime.Now.AddHours(1);
   ai.Save();
}



viel erfolg

09.11.2005 - 16:55 Uhr

hallo leute, beisse mir immer noch die zähne an meinem bitmap memorystream aus:

ich habe ein bitmap als datei gespeichert, die lese ich mit nachstehendem code und erhalte ein bytearray mit länge 3126:

FileStream fStream = new FileStream("C:\\test.bmp", FileMode.Open);
Byte[] fByte = new byte[fStream.Length];
fStream.Read(fByte, 0, (int)fStream.Length);
Bitmap picture = new Bitmap(fStream); ;
fStream.Close(); 

das gleiche mache ich nun mit einem memory stream aus einer tabelle, deren datenfeld vom typ Image ist und das ich explizit mit der gleichen datei gefüllt habe.

mit nachstehendem code (equivalent zu oben) lese ich den stream und kriege jetzt 3220 byte länge. daher schlägt meiner meinung nach die zuweisung für picture = ..." fehl: ich bekomme ständig den laufzeitfehler "Parameter not valid."

MemoryStream mStream = new MemoryStream((Byte[])record["Picture"]);  
Byte[] mByte = new byte[mStream.Length];
mStream.Read(mByte, 0, (int)mStream.Length);
Bitmap picture = new Bitmap(mStream); 
mStream.Close();

debug ergab, dass ab position 72 das längere (also fehlerbehaftete tabellen-) feld mit dem filestream übereinstimmt, aber dann anscheinend nur bis zu einer bestimmten endposition, denn 3220 -3126 != 72...

cracks vor!
ich dreh hier nämlich gleich durch 🤔

thanx

ron

09.11.2005 - 16:06 Uhr

genau, und man darf auch nicht über eine rote fussgängerampel gehen und beim autofahren nicht telefonieren und bei tisch nicht in der nase bohren...

09.11.2005 - 16:03 Uhr

über das eigenschaftenfenster der ide???

klar ist das tag ein object, das ist ja das problem: wie bettest du denn da z.b über die ide sagen wir mal ein button ein?

oder, wie gesagt, die ZAHL 2 statt "2".

schreib dochmal 2 in das tag eines controls und guck dir dann im designer.cs an, was der säckel draus gemacht hat...

09.11.2005 - 15:52 Uhr

so, jetz mussisch hier ma aufn putz haun...

Weil fast jeder Noob trotz Dutzender Warn-Hinweise mindestens einmal in InitializeComponents() rumgemacht hat.

es gibt situationen, in denen es sogar zwingend notwendig ist, im designer und InitializeComponents "rumzumachen", oder wie bringt ihr oberschlaumeier sonst fertig, in den Tag eines steuerelements im einfachsten fall die zahl 2 statt der zeichenkette "2" reinzulegen oder gar ein noch komplexeres objekt ?

wahrscheinlich schreibt ihr das auch in "euren" erlaubten dateiteil, gelle?

brav!

macht weiter so, ich bleib´ dabei: keine ide der welt hindert mich daran, in ihrem code "rumzumachen" !

bussy

ron 8)

09.11.2005 - 12:29 Uhr

hi fzelle,

Das ist ja gerade einer der Vorteile von C#, das diese Sachen nicht mehr
getrennt gespeichert werden, und du willst wieder C einführen.

dann frage ich mich, warum die ide von sich aus schon in verschiedene dateien aufteilt; schließlich steht in der myForm.Designer.cs nichts, was nicht auch in der myForm.cs selbst stehen könnte, habe ich sogar schon ausprobiert.

in meinem fall geht es darum, dass mir regions nicht mehr ausreichen, um eine kategorisch gegliederte aufteilung bestimmter code segmente in meinem mutterformular zu erreichen.

ansonsten stimme ich dir nämlich grundsätzlich zu, dass eine modularisierung bis ins kleinste natürlich albern ist und das tue ich sonst auch nicht.

also, danke für den typ, der hat nämlich tatsächlich geholfen... 🙂

ron

09.11.2005 - 12:07 Uhr

hi leute,

ich möchte das bild eines toolstripbuttons aus einem stream laden.
das bitmap ist 32x32 mit 24bit farbtiefe und soll weiss als transparente farbe aufweisen.

hierbei kommt es zu folgenden schwierigkeiten:

dieser code funktioniert:

   
FileStream fStream = new FileStream("C:\\helmet.bmp", FileMode.Open);
_Picture = new Bitmap(fStream, true);
fStream.Close(); 

dieser code lädt die exakt gleiche bitmap aus einem Image-Feld einer SQL Server Datenbanktabelle und kracht mit fehlermeldung "Parameter not valid" in der zuweisung von _Picture = ...:

   MemoryStream mStream = new MemoryStream((Byte[])record["Picture"]);
_Picture = new Bitmap(mStream, true);

der mStream ist aber mit gültigen werten belegt.

das zweite problem ist in der späteren nutzung des bildes im toolstripbutton

das verfl... programm kracht bei der zuweisung "tsb.ImageTransparentColor =... " mit einer out of memory-exception.


   
ToolStripButton tsb = new ToolStripButton(vw.Label, vw.Picture);
tsb.Name = "bla";
tsb.CheckOnClick = true;
tsb.ImageTransparentColor = Color.White;
tsb.DisplayStyle = ToolStripItemDisplayStyle.Image;
tsb.Image = _Picture;
tsb.Size = new System.Drawing.Size(23, 28);

dabei spielt die code position der zuweisung keine rolle, hab´s an allen stellen probiert.

tips von euch retten meinen tag 😁

ron

09.11.2005 - 10:08 Uhr

hi leute,

ich möchte ein image aus einer tabelle meiner sql datenbank laden.
Das feld heißt [Picture] und der felddatentyp ist Image.

DataRow record;
Image     picture;
...
picture = (record["Picture"].Equals(DBNull.Value)) ? null : (Image)record["Picture"];

Der Laufzeitfehler besagt sinngemäß, dass die konvertierung von byte nach image nicht geht, was mich vermuten lässt, dass es so einfach wie oben implementiert dann doch nicht geht...

vermutlich muss ich das image aus einem bytestream lesen?
und wenn ja: wie gehd dem??? ?(

danke für eure hilfe.

09.11.2005 - 09:22 Uhr

hi leute,

wenn man eine formulardatei anlegt, bekommt man ja in vs 2005 mehrere dateien, z.B.:

myForm.Designer.cs
|_ myForm.cs
|_ myForm.resx

wenn ich jetzt zusätzliche dateien hierzu anlegen möchte, gelingt mir das natürlich über das schlüsselwort "partial class" und über entsprechende namensvergabe, z.B:

myForm.Members.cs
myForm.Methods.cs usw...

diese dateien werden im explorer aber nicht wirklich der formulardatei untergeordnet und mit einem entsprechenden symbol versehen; mit anderen worten: die ide "weiss" vermutlich also nicht, dass zu der hauptdatei noch meine unterdateien gehören.

gibts dafür ne anweisung in der ide oder was anderes, das ich noch tun muss?

danke für eure hilfe

ron

09.11.2005 - 09:13 Uhr

hi psorin,

ich lade ebenfalls mit gleicher methode eigene dll´s.

die 30 sekunden kann ich nicht nachvollziehen, eher so 5 bis 8 sek.

vielleicht sind in deiner dll formulare mit vielen resourcen?

ansonsten könntest du die dinger im rahmen der anwendungsinitialisierung erstmal alle "anladen", so dass sie im späteren anwendungsverlauf schneller verfügbar sind.

gruß
ron

09.11.2005 - 08:54 Uhr

hi timo,

bin mit xml noch gar nicht warm geworden, daher vielleicht die unwissende frage:

wie löst du denn mit xml files die verschiedenen einstellungen unterschiedlicher benutzer? über knoten in der gleichen datei?

09.11.2005 - 08:42 Uhr

hi leute,

habe in einem .net buch gelesen, dass es kein guter stil mehr sein soll, die registry zu nutzen, um bestimmte anwendungsparameter zu hinterlegen; stattdessen sollte man lieber die cfg-dateien der anwendung verwenden.

könnt ihr das so unterschreiben?

was ist gegen die registry auszusetzen?

und ist es nicht bei der cfg-datei so, dass sie pro rechner nur einmal existiert (nämlich im pfad der anwendung) und ich daher nicht für mehrere benutzer verschiedene angaben speichern kann (was ich in der registry unter local user ja sehr wohl kann) ?

danke für eure meinung

ron

09.11.2005 - 07:49 Uhr

hi leute,

wenn man eine formulardatei anlegt, bekommt man ja in vs 2005 mehrere dateien, z.B.:

myForm.Designer.cs
|_ myForm.cs
|_ myForm.resx

wenn ich jetzt zusätzliche dateien hierzu anlegen möchte, gelingt mir das natürlich über das schlüsselwort "partial class" und über entsprechende namensvergabe, z.B:
( myForm.Members.cs
myForm.Methods.cs usw...

diese dateien werden im explorer aber nicht wirklich der formulardatei untergeordnet und mit einem entsprechenden symbol versehen; mit anderen worten: die ide "weiss" vermutlich also nicht, dass zu der hauptdatei noch meine unterdateien gehören.

gibts dafür ne anweisung in der ide oder was anderes, das ich noch tun muss?

danke für eure hilfe

ron

01.11.2005 - 17:38 Uhr

hey herbivore,

kann mir einer der Singelton-Anhänger mal den Vorteil gegenüber static erklären?

genau die gleiche frage hätte ich jetzt als nächstes auch gestellt.

schließlich spart man sich bei static zusätzlich noch den aufruf der Konstruktoren in allen klassen und programmierer sind schließlich code ökonomen... 😁

01.11.2005 - 17:17 Uhr

hi leute,

da sieht man´s mal wieder, hätte mich dochmal mit design patterns beschäftigen sollen.

hab mir beispielcode dazu mal angeguckt und glaube, dass der singleton eine gute idee ist, danke.

wenn ich´s richtig verstanden habe, würde jede klasse dann zwar seinen "eigenen" messenger instantieren müssen, aber weil´s ein singleton ist, kommt immer das gleiche objekt zurück, oder?

01.11.2005 - 16:42 Uhr

hi spezialies,

mal wieder ne konzeptionelle frage:

ich habe eine klasse gebaut namens Messenger, die so Sachen übernimmt, wie alle möglichen nachrichten an alle möglichen Ziele zu verteilen, z.b. logfiles schreiben, gravierende anwendungsfehler an leute vermailen, windows event log schreiben usw. usw.
natürlich dient der messenger damit an vielen punkten meiner anwendung auch als protokollant (z.b. in der logdatei), ob irgendwas geklappt hat oder nicht, so eine art debugger im produktivbetrieb...

aus diesem grund muss natürlich so ziemlich jede selbst geschriebene klasse meiner anwendungen den messenger kennen.

dies wiederum führt dazu, dass

  1. jede klasse die klasse messenger einbinden und auf sie verweisen muss
  2. jede klasse der anwendung im konstruktor oder später den messenger übergeben bekommen muss.

punkt zwei könnte man sich meiner meinung nach sparen, wenn der messenger statisch ist.

ist der messenger damit ein idealer kandidat für eine statische klasse oder bleibt man aus gründen der objektorientierten philosophie lieber bei der aktuellen vorgehensweise ?

danke für eure meinung

ron

01.11.2005 - 15:49 Uhr

hi pedro

da ich mit .net 2.0 / vs 2005 angefangen habe und 2003 kaum kenne, bin ich mir nicht sicher, ob es das Dictionary dort schon gab:

      

      Dictionary < string, MyObjClass> dict;
      MyObjClass obj = new MyObjClass(...);
      dict.Add("myKey_1", obj);

      ...

      // und der Zugriff ist dann möglich mit:

      MyObjClass anotherObj = dict["myKey_1"];

wenn nicht, steig einfach auf 2005 um, ist eh um welten besser 😉

29.10.2005 - 11:15 Uhr

hi progger,

herzlichen glückwunsch und viel spass beim lesen!

kleiner lesetipp:
da das buch für die bettlektüre zeimlich schwer ist (im sinne von kilos!!!) habe ich als erstes das inhaltsverzeichnis herausgerissen und mental implementiert 8o

danach wusste ich dann so ungefähr, welche kapitel mich in welcher reihenfolge interessieren.
ausserdem habe ich meistens mit der zusammenfassung der kapitel angefangen und es dann vertieft, wenn´s gut war.

kannst ja in diesem thread abundzu mal deine meinung zu ein paar kapiteln äußern...

28.10.2005 - 11:38 Uhr

hallo leute,

hat jemand von euch unter .net 2.0 schonmal versucht, Hilfetexte für den Benutzer in einer Statusleiste anzuzeigen?

Kann es sein, dass die mitgelieferte Textbox dahingehend keine vernünftigen Eigenschaften mitbringt? (Den Tag brauche ich schon für andere Dinge).

Kann doch nicht sein, dass man für solcherlei Absichten nun alle betreffenden Steuerelemente (also; Textbox, DropDownListen, Checkboxen, etc.) erstmal erben muss, um die fehlenden Properties hinzuzufügen, oder? (Schluck) 🙁