Laden...

Wie kann bei einer Multiline textBox auf jeder Zeile ein "X" Remove Button erstellt werden ?

Erstellt von Tom.Net vor 5 Jahren Letzter Beitrag vor 5 Jahren 2.065 Views
T
Tom.Net Themenstarter:in
10 Beiträge seit 2018
vor 5 Jahren
Wie kann bei einer Multiline textBox auf jeder Zeile ein "X" Remove Button erstellt werden ?

Hallo zusammen

Ich versuche nun schon seit einiger Zeit Folgendes zu realisieren:

In eine Multiline textBox (Einfacher Shop) werden Artikel über einen Button Zeilenweise untereinander eingefügt. Nun soll ein "X" (Remove) Button in jeder einzelnen eingefügten Zeile erscheinen, damit man bei Fehleinträgen die btreffende Zeile (inkl. dem dazugehörigen Button) wieder aus der Liste entfernen kann.

Das einfügen von fortlaufend nummerierten Zeilen funktioniert. Da bekomme ich auch einen Button rein, doch den kann ich noch nicht dazu bewegen, die entsprechende Zeile und sich selbst wieder zu entfernen. Im weiteren erscheint der Button nur ein einziges mal statt auf jeder Zeile die eingefügt wird.

Kann mir da jemand auf die Sprünge helfen? Vielen Dank.



float Nummer = 0;
float Zeile = 0;        
float SubTotal = 0;
float MwSt = 0;
float Total = 0;

private void btnShop1_Click(object sender, EventArgs e)                                                                                                                
{
    tabControlShop1.SelectedTab = tabWarenkorbShop;
    
    Nummer = Nummer + 1;
            
    txtWarenkorbShop.AppendText(" " + Nummer + "\t" + "  " + "Artikel_1" + "\t" + txtPreis1.Text + Environment.NewLine);            
    Zeile += float.Parse(txtPreis1.Text);

    Button btn = new Button();
    btn.Parent = txtWarenkorbShop;
    btn.BringToFront();            
    btn.Size = new Size(18, 18);
    btn.Text = "X";
    btn.ForeColor = Color.Red;                     
    txtWarenkorbShop.Controls.Add(btn);            
            
    Total = Zeile;            
    MwSt = Total / 100 * 7;
    SubTotal = Zeile - MwSt;
    mwst();
    subtotal();            
    total();       
}

709 Beiträge seit 2008
vor 5 Jahren

Moin Tom.Net,
bist du sicher, dass du dafür eine TextBox und kein anderes Steuerelement verwenden willst?
Ich denke, dass eine TextBox dafür eher ungeeignet ist.

T
Tom.Net Themenstarter:in
10 Beiträge seit 2018
vor 5 Jahren

Hallo pinki, bin noch nicht so bewandert mit C# und kann daher noch nicht genau sagen, was dafür die beste Wahl ist. Wäre eine ListBox besser geeignet ?

T
Tom.Net Themenstarter:in
10 Beiträge seit 2018
vor 5 Jahren

Damit schaffe ich es schon mal Zeile um Zeile zu löschen.


txtWarenkorbShop.Text = txtWarenkorbShop.Text.Remove(txtWarenkorbShop.Text.LastIndexOf(Environment.NewLine));

1.029 Beiträge seit 2010
vor 5 Jahren

Hi,

du hast tabellarische Daten - also solltest du auch eine richtige Tabelle verwenden.

Unter WindowsForms wäre das ein DataGridView - da würde ich an deiner Stelle mal 1-2 Tutorials anschauen und dann damit experimentieren.

LG

T
Tom.Net Themenstarter:in
10 Beiträge seit 2018
vor 5 Jahren

Hi Taipi88, dann müsste ich wohl eine Datenbank als Quelle erstellen. Das wäre dann aber nicht mehr im Sinne dieser kleinen Anwendung. Ich habe ein Tool dass das Selbe mit einer TextBox macht, habe aber den Source leider nicht. Daher gehe ich mal davon aus, dass es eine einfache Lösung geben muss. In meinem Beispiel bekomme ich ja schon den entsprechenden Button (btn) in die erste Zeile. Was mir jetzt noch fehlt sind lediglich zwei Dinge:

  1. Der Button (btn) erscheint nur in der ersten Zeile. Beim zweiten Click auf (btnShop1) erscheint korrekterweise eine weitere fortlaufend nummerierte Zeile, aber ohne den Button. Am einfachsten wäre es wenn ich den (btn) einfach an "txtWarenkorbShop.AppendText(...)" anhängen könnte. Geht aber wohl nicht, da Controls nicht als Text behandelt werden können. Ausser da gäbe es einen Trick.

  2. Ich kann dem Button (btn) keine Aktion zuordnen, die da sein sollte "lösch diese Zeile und mich selbst", ausser im Foem wird ein separater Butto erstellt und mit (btn) verknüpft. Dann sind Aktionen wie "Remove(txtWarenkorbShop.Text.LastIndexOf(Environment.NewLine)" oder "txtWarenkorbShop.Text.Remove(40, 40)" möglich.

1.029 Beiträge seit 2010
vor 5 Jahren

Hi,

was hat denn in deinen Augen ein DataGridView mit einer Datenbank zu tun?

Ein DataGridView lässt sich an unterschiedlichste Listen binden - sogar gegen ein simples Array. Zugegeben - auch an DataTables und DataViews (welche sich übrigens ebenfalls ohne Datenbank verwenden lassen).

Der Tip ging nur um Folgendes: Du versuchst mit Textboxen und Buttons eine Lösung zu erstellen, die ein DataGridView bereits im Standard (und deutlich hübscher) beherrscht.

Als Beispiel (sollte ändern, löschen und hinzufügen bereits beherrschen, für das Hinzufügen solltest du ggf. aber separate Controls hinzufügen):


using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Forms;

namespace WindowsFormsApp3
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            var articles = new ObservableCollection<Article>(new []
            {
                new Article {Name = "Artikel 1", Price = 20},
                new Article {Name = "Artikel 2", Price = 30}
            });
            
            var dgv = new DataGridView
            {
                Dock = DockStyle.Fill,
                AutoGenerateColumns = false
            };

            dgv.Columns.Add(new DataGridViewTextBoxColumn {HeaderText = "Name", DataPropertyName = "Name"});
            dgv.Columns.Add(new DataGridViewTextBoxColumn {HeaderText = "Preis", DataPropertyName = "Price"});
            dgv.Columns.Add(new DataGridViewButtonColumn {Text = "Löschen", UseColumnTextForButtonValue = true});

            dgv.CellClick += (sender, args) =>
            {
                if (!(dgv.Columns[args.ColumnIndex] is DataGridViewButtonColumn) || args.RowIndex < 0) return;
                dgv.Rows.RemoveAt(args.RowIndex);
            };
            
            dgv.DataSource = new BindingList<Article>(articles);
            Controls.Add(dgv);

            articles[0].Name = "Test;";
            articles.Add(new Article {Name = "Test 2", Price = 10});
        }
    }

    public class Article
    {
        public string Name { get; set; }

        public decimal Price { get; set; }
    }
}

PS: Die BindingList unten bei der Zuweisung an die DataSource sorgt im Endeffekt dafür, dass DataGridView mittels BindingList mit der ObservableCollection kommuniziert.

PPS: Das DataGridView erweitert seine Fähigkeiten je nachdem welche Art von Liste gebunden wird - für simple Listen ist das lediglich Anzeige. Eine IBindingList (wie hier) kriegt Support für Änderungen an den Listen. Für eine Implementierung von IBindingListView (z.B. eine DataView) gibts von Haus aus Sortieren, Filtern & Co. geschenkt.

LG

T
Tom.Net Themenstarter:in
10 Beiträge seit 2018
vor 5 Jahren

Dieses einfache Beispiel macht schon annähernd dass was ich will. Die unteren Zeilen müssten aber noch nachrutschen, so dass keine leere Zeile übrig bleibt. Liegt wahrscheinlich daran dass der Button noch nicht gelöscht wird.


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

namespace Daten_zu_TextBox_Test
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Button btn = new Button();
            btn.Click += new EventHandler(btn_Click);           
            btn.Size = new Size(18, 18);
            btn.Text = "X";
            btn.ForeColor = Color.Red;                  
            textBox2.Controls.Add(btn);
           
            string sent = ("\t" + "Testline");

            textBox2.AppendText(sent);
            textBox2.AppendText(Environment.NewLine);
        }

        void btn_Click(object sender, EventArgs e)
        {            
            textBox2.Text = textBox2.Text.Remove(1, textBox2.Lines[1].Length + 0 );
        }   
       
    }
}

T
Tom.Net Themenstarter:in
10 Beiträge seit 2018
vor 5 Jahren

@Taipi88 vielen Dank für die Erläuterungen. Das werde ich gleich testen. Ich nehme an, die Grid-Struktur kann ausgeblendet werden. Mit der TextBox Variante bin ich auch etwas weiter gekommen.