none
C# "Progressbar" wie beim Defragmentieren? RRS feed

  • Frage

  • Ich  suche eine Art Progress bar, wie sie häufig beim Defragmentieren eingesetzt wird (Bild: http://s14.directupload.net/images/140519/lg8fjlcu.gif)

    Ich habe es schon mit einer Listview und kleinen Items Probiert, aber ich bekomme das einfach nicht schön hin. Vlt hat ja jemand von euch eine Idee. 

    Montag, 19. Mai 2014 15:50

Antworten

  • Ok, in WinForms ist es zwar nicht ganz so einfach wie in WPF, aber auch möglich. Gucke dir mal folgenden Code an:
    public partial class UserControl1 : UserControl
    {
        public UserControl1()
        {
            this.Bars = new ObservableCollection<ColorItem>();
            this.Bars.CollectionChanged += Bars_CollectionChanged;
            InitializeComponent();
        }

        void Bars_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            this.Invalidate();//Wenn sich die Auflistung ändert, neu Zeichnen
    //Wenn sich ein Item ändert, musst du die Grafik manuell korrigieren
        }

        public ObservableCollection<ColorItem> Bars { get; private set; }

        private void UserControl1_Paint(object sender, PaintEventArgs e)
        {
            int left = 0;
            foreach (var bar in this.Bars)//Alle Balken durchlaufen und zeichnen
            {
                int width = (int)(this.Width * bar.Percent);
                e.Graphics.FillRectangle(new SolidBrush(bar.Color), left, 0, width, this.Height);
                left += width;
            }
        } } public class ColorItem { public ColorItem(Color c, double p) { this.Color = c; this.Percent = p; } /// <summary> /// Ruft die Farbe ab in der der Streifen gemald werden soll oder legt diese fest. /// </summary> public Color Color { get; private set; } /// <summary> /// Ruft die Breite des Streifens in Prozent zur Gesamtgröße ab oder legt diese Fest.<para /> /// Der erlabte Wertebereich ist 0 bis 1. /// </summary> public double Percent { get; set; } }
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    
        private void Form1_Load(object sender, EventArgs e)
        {
            userControl11.Bars.Add(new ColorItem(Color.Red, 0.15));
            userControl11.Bars.Add(new ColorItem(Color.Green, 0.05));
            userControl11.Bars.Add(new ColorItem(Color.Yellow, 0.1));
            userControl11.Bars.Add(new ColorItem(Color.Orange, 0.15));
            userControl11.Bars.Add(new ColorItem(Color.Blue, 0.25));
            userControl11.Bars.Add(new ColorItem(Color.Purple, 0.1));
            userControl11.Bars.Add(new ColorItem(Color.Cyan, 0.1));
            userControl11.Bars.Add(new ColorItem(Color.LightCoral, 0.1));
        }
    
        private void Form1_Resize(object sender, EventArgs e)
        {
            userControl11.Invalidate();//Control neu zeichnen, wenn sich die Formgröße verändern (Anchor ist zum testen auf Alle Seiten eingestellt)
        }
    }
    Du musst bei dem Code nur aufpassen, dass du nicht zu viele Balken anzeigst, weil sonst Rechtecke mit der Breite 0 berechnet werden. Diese werden dann nicht gezeichnet.



    Tom Lambert - C# MVP
    Bitte bewertet- und markiert Beiträge als Antwort. Danke.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets


    Montag, 19. Mai 2014 16:23
    Moderator

Alle Antworten

  • Hallo,
    mit welcher Technologier arbeitest du denn (WPF, WinForms, ...)?

    In Windows Forms würde ich es mit einem CustomControl probieren und die Striche im Paint-Event zeichen.

    In WPF dagegen mit einem gebundenen ItemsControl, welches ein StackPanel oder Grid als ItemsPanel hat. Jedes Item wäre dann nur 1 Pixel breit.


    Tom Lambert - C# MVP
    Bitte bewertet- und markiert Beiträge als Antwort. Danke.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Montag, 19. Mai 2014 15:57
    Moderator
  • Sorry hab ich vergessen, ich arbeite in einer Windows Forms Anwendung.
    Montag, 19. Mai 2014 16:00
  • Das ist ja so was Ähnliches wie ein Barcode nur in Farbe. Für den Barcode kannst du hier eine Anleitung finden. Die Erweiterung für die Farbe sollte, dann nicht mehr so schwer sein.

    MFG

    Björn

     
    Montag, 19. Mai 2014 16:11
  • Ok, in WinForms ist es zwar nicht ganz so einfach wie in WPF, aber auch möglich. Gucke dir mal folgenden Code an:
    public partial class UserControl1 : UserControl
    {
        public UserControl1()
        {
            this.Bars = new ObservableCollection<ColorItem>();
            this.Bars.CollectionChanged += Bars_CollectionChanged;
            InitializeComponent();
        }

        void Bars_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            this.Invalidate();//Wenn sich die Auflistung ändert, neu Zeichnen
    //Wenn sich ein Item ändert, musst du die Grafik manuell korrigieren
        }

        public ObservableCollection<ColorItem> Bars { get; private set; }

        private void UserControl1_Paint(object sender, PaintEventArgs e)
        {
            int left = 0;
            foreach (var bar in this.Bars)//Alle Balken durchlaufen und zeichnen
            {
                int width = (int)(this.Width * bar.Percent);
                e.Graphics.FillRectangle(new SolidBrush(bar.Color), left, 0, width, this.Height);
                left += width;
            }
        } } public class ColorItem { public ColorItem(Color c, double p) { this.Color = c; this.Percent = p; } /// <summary> /// Ruft die Farbe ab in der der Streifen gemald werden soll oder legt diese fest. /// </summary> public Color Color { get; private set; } /// <summary> /// Ruft die Breite des Streifens in Prozent zur Gesamtgröße ab oder legt diese Fest.<para /> /// Der erlabte Wertebereich ist 0 bis 1. /// </summary> public double Percent { get; set; } }
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    
        private void Form1_Load(object sender, EventArgs e)
        {
            userControl11.Bars.Add(new ColorItem(Color.Red, 0.15));
            userControl11.Bars.Add(new ColorItem(Color.Green, 0.05));
            userControl11.Bars.Add(new ColorItem(Color.Yellow, 0.1));
            userControl11.Bars.Add(new ColorItem(Color.Orange, 0.15));
            userControl11.Bars.Add(new ColorItem(Color.Blue, 0.25));
            userControl11.Bars.Add(new ColorItem(Color.Purple, 0.1));
            userControl11.Bars.Add(new ColorItem(Color.Cyan, 0.1));
            userControl11.Bars.Add(new ColorItem(Color.LightCoral, 0.1));
        }
    
        private void Form1_Resize(object sender, EventArgs e)
        {
            userControl11.Invalidate();//Control neu zeichnen, wenn sich die Formgröße verändern (Anchor ist zum testen auf Alle Seiten eingestellt)
        }
    }
    Du musst bei dem Code nur aufpassen, dass du nicht zu viele Balken anzeigst, weil sonst Rechtecke mit der Breite 0 berechnet werden. Diese werden dann nicht gezeichnet.



    Tom Lambert - C# MVP
    Bitte bewertet- und markiert Beiträge als Antwort. Danke.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets


    Montag, 19. Mai 2014 16:23
    Moderator
  • Danke für deine Antwort und das tolle Code Beispiel, aber ich bekomme folgenden Fehler:

    Inkonsistenter Zugriff: Eigenschaftentyp 'System.Collections.ObjectModel.ObservableCollection<test.ColorItem>' ist weniger zugreifbar als Eigenschaft 'test.StrichBar.Bars' C:\Users\lukas_000\documents\visual studio 2013\Projects\test\test\StrichBar.cs 28 48 test

    Zur Erklärung:

    test ist mein Forms Projekt und 

    StrichBar ist mein User Control

    Montag, 19. Mai 2014 17:17
  • Eine Eigenschaft der Klasse ist z.B. private und in der andern Klasse wird sie über public Eigenschaft/Methode sichtbarer gemacht.
    Montag, 19. Mai 2014 17:25
  • der Fehler kommt in dieser Code-Zeile:

     public ObservableCollection<ColorItem> Bars { get; private set; }

    Montag, 19. Mai 2014 17:37
  • Ich vermute mal, das du das public vor ColorItem vergessen hast.

    Tom Lambert - C# MVP
    Bitte bewertet- und markiert Beiträge als Antwort. Danke.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Montag, 19. Mai 2014 18:20
    Moderator
  • Schau mal ob du die Klasse ColorItems als Public declariert hast.

    Als Standard beim hinzufügen einer Klasse wird kein Sichtbarkeitsmodifizierer gesetzt, was dann private entspricht.

    Montag, 19. Mai 2014 18:23