DataListView [ListView mit Komplexer Datenbindung und Einbettbaren Steuerelementen]

    • Release
    • Open Source

    Es gibt 2 Antworten in diesem Thema. Der letzte Beitrag () ist von Fakiz.

      DataListView [ListView mit Komplexer Datenbindung und Einbettbaren Steuerelementen]

      Name:
      DataListView

      Beschreibung:
      Das Projekt ist entstanden da ich einen etwas tieferen Einblick in die Komplexe Datenbindung erhalten wollte. Ich habe also eine normale Listview um Komplexe Datenbindung erweitert. Um das ganze noch etwas abzurunden habe ich noch Auf und zu klappbare ListViewGroups Implementiert.
      Dabei habe ich mich an diesem Projekt orientiert: Collapsible-ListViewGroup
      Was ich noch vergessen habe zu erwähnen, die DataListView verfügt nun auch über die Methoden .Save() & .Load() welche es ermöglichen den Inhalt der DataListView als XML zu speichern bzw. eine XML direkt zu laden.




      *Update*
      Quellcode wurde überarbeitet, PropertyGrid -Eigenschaften für ColumnHeaderResizeStyle wurden frei gegeben. Der Source liegt nun eine Beispiel Anwendung bei.


      *Udate 1*

      Inline -Bearbeitung bei Detail -Ansicht wurde dem Steuerelement hinzugefügt. Anhand eines Integer -Arrays lassen sich die Columns die bearbeitet werden dürfen festlegen. Bleibt das Array leer können alle SubItems bearbeitet werden. Für die erste Column wird weiterhin die Eigenschaft LabelEdit verwendet. Wurden Werte tatsächlich geändert werden diese auch an die zugrunde liegende DataSource weitergegeben.


      *Update 2*

      Eingebettete Steuerelemente wurden der DataListView hinzugefügt. Es ist nun möglich einem ListViewItem bzw. SubItem ein Steuerelement zuzuweisen. Diese werden wenn sich die DataListView in der Detail -Ansicht befindet angezeigt.


      *Update 2.1*


      Da mir die normale ProgressBar nicht gefallen hat habe ich nun eine eigene hinzugefügt.

      *Update 2.2 (RC)*
      Source wurde überarbeitet

      *Update 2.2.1 (RC)*
      An stelle der normalen CheckBox wird nun eine eigene verwendet. Diese wird nun in der Mitte des jeweiligen Items angezeigt und ohne Text. Damit sieht das ganze mehr Windows konform aus.

      *Update Version 1.0.0.1*


      *Update*
      Letztes Update


      Klassendiagramm:



      Bekannte Bugs:
      Bislang keine


      Anwendungs Snippet für DataListViewControls

      C#-Quellcode

      1. /*
      2. * Fügt der DataListView ein NummericUpDown Steuerelement
      3. * und eine Progressbar hinzu...
      4. * Im Anschluss wird die Höhe der Zeile an die Höhe des NummericUpDown angepasst.
      5. */
      6. dataListView1.Columns.Add("Item");
      7. dataListView1.Columns.Add("Progressbar");
      8. dataListView1.Columns.Add("NumericUpDown");
      9. DataListView.ListViewItem dItem = new DataListView.ListViewItem(dataListView1, "DataListViewItem", DataListView.EmbeddableControl.NummericUpDown, 1);
      10. dItem.AddControl(DataListView.EmbeddableControl.Progressbar, 2);
      11. ((NumericUpDown)dItem.GetControl(1)).Value = 8;
      12. ((DataListView.ProgressBar)dItem.GetControl(2)).Value = 86;
      13. dataListView1.Items.Add(dItem);
      14. dataListView1.RowHeight = ((NumericUpDown)dItem.GetControl(1)).Height;
      15. dataListView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);


      VB.NET-Quellcode

      1. /*
      2. * Fügt der DataListView ein NummericUpDown Steuerelement
      3. * und eine Progressbar hinzu...
      4. * Im Anschluss wird die Höhe der Zeile an die Höhe des NummericUpDown angepasst.
      5. */
      6. dataListView1.Columns.Add("Item")
      7. dataListView1.Columns.Add("Progressbar")
      8. dataListView1.Columns.Add("NumericUpDown")
      9. Dim dItem As New DataListView.ListViewItem(dataListView1, "DataListViewItem", DataListView.EmbeddableControl.NummericUpDown, 1)
      10. dItem.AddControl(DataListView.EmbeddableControl.Progressbar, 2)
      11. DirectCast(dItem.GetControl(1), NumericUpDown).Value = 8
      12. DirectCast(dItem.GetControl(2), DataListView.ProgressBar).Value = 86
      13. dataListView1.Items.Add(dItem)
      14. dataListView1.RowHeight = DirectCast(dItem.GetControl(1), NumericUpDown).Height
      15. dataListView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize)




      Programmiersprache/Entwicklungsumgebung

      c# / VisualStudio

      Systemanforderungen:
      .Net 2.0

      Download(s):
      Siehe Dateianhänge...
      Prüfsumme [sha256] Control: 6D48C41D0C9091BAAEB796922411FCAA703B86D3269F534A2F7B1471D91DE291
      Prüfsumme [sha256] Source: 85C8CD5DE448927B684AE443215A0A05B20C5F15D6B02EF33777110FE5609941

      Lizenz/Weitergabe:
      Unterliegt keiner Lizenz
      Dateien

      Dieser Beitrag wurde bereits 52 mal editiert, zuletzt von „Fakiz“ ()

      Anwendungs -Beispiel

      Da sich das Projekt dem Ende nähert habe ich nun noch ein kleines Anwendungs -Beispiel erstellt, einen schlichten MultiDownloader, der einige der neuen Funktionen nutzt.



      Das ganze funktioniert folgendermaßen:
      per Drag&Drop wird eine Textdatei in der zeilenweise Downloadlinks eingetragen wurden in die DataListView fallen gelassen. Nun wird diese Textdatei zeilenweise ausgelesen und jede Zeile wird einer Generischen Liste hinzugefügt. Nach dem befüllen der Liste wird diese der DataListView als DataSource übergeben. Nun werden 2 Methoden aufgerufen eine Methode ergänzt die bereits vorhandenen ColumnHeader, die andere fügt jedem Link (DataListView.ListViewItem) eine Progressbar hinzu und ein weiteres SubItem welches für die Downloadgeschwindigkeit steht.
      Durch betätigen des Buttons wird der ThreadPool des MultiDownloaders auf die Anzahl der DataListView -Items gesetzt und jedes Item an den ThreadPool übergeben. Nun wird für jedes Item eine Klasse (Downloader) Instanziert, diese Klasse übernimmt den Download und verfügt über einen ProgressChanged -Event.


      Source Form

      Form_Load

      C#-Quellcode

      1. // Beinhaltet alle Progressbars der DataListView, erleichtert die Handhabung
      2. List<DataListView.ProgressBar> pbList;
      3. // Speicherpfad für Downloads
      4. DirectoryInfo diSavePath = new DirectoryInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "MultiDownloader"));
      5. private void Form1_Load(object sender, EventArgs e)
      6. { pbList = new List<DataListView.ProgressBar>(); }



      Downlaod starten

      C#-Quellcode

      1. private void button_startDownloads_Click(object sender, EventArgs e)
      2. {
      3. if (dataListView_downloadList.Items.Count > 0) {
      4. // Threadpool Threads setzen
      5. System.Threading.ThreadPool.SetMaxThreads(dataListView_downloadList.Items.Count, dataListView_downloadList.Items.Count);
      6. // Downloads an den ThreadPool übergeben
      7. foreach (DataListView.ListViewItem dItem in dataListView_downloadList.Items)
      8. System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(DownloadThreadCallback), dItem);
      9. }
      10. }
      11. // ThreadPool Callback
      12. private void DownloadThreadCallback(object item)
      13. {
      14. DataListView.ListViewItem dItem = (DataListView.ListViewItem)item;
      15. string url ="";
      16. int index=0;
      17. dataListView_downloadList.Invoke(new MethodInvoker(delegate()
      18. {
      19. url = dItem.Text;
      20. index = dItem.Index;
      21. }));
      22. using (Downloader dl = new Downloader(url, diSavePath, index))
      23. dl.OnProgressChanged += OnProgressChanged;
      24. }



      Drag&Drop + Methode AddColumns() & AddItems()

      C#-Quellcode

      1. private void dataListView_downloadList_DragDrop(object sender, DragEventArgs e)
      2. {
      3. if (e.Data.GetDataPresent(DataFormats.FileDrop)) {
      4. string[] sa = (string[])e.Data.GetData(DataFormats.FileDrop);
      5. List<string> dlList = new List<string>();
      6. foreach (string s in sa)
      7. if (s.EndsWith(".txt"))
      8. using (StreamReader sr = new StreamReader(s)) {
      9. string line;
      10. while ((line = sr.ReadLine()) != null)
      11. dlList.Add(line);
      12. }
      13. dataListView_downloadList.DataSource = dlList;
      14. AddColumns();
      15. AddItems();
      16. dataListView_downloadList.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
      17. }
      18. }
      19. private void dataListView_downloadList_DragEnter(object sender, DragEventArgs e)
      20. {
      21. if (e.Data.GetDataPresent(DataFormats.FileDrop)) { e.Effect = DragDropEffects.All; }
      22. else { e.Effect = DragDropEffects.None; }
      23. }
      24. private void AddColumns()
      25. {
      26. if (dataListView_downloadList.Columns.Count > 0) {
      27. dataListView_downloadList.Columns[0].Text = "Download URL";
      28. dataListView_downloadList.Columns.Add("Download Status");
      29. dataListView_downloadList.Columns.Add("KB/s");
      30. }
      31. }
      32. private void AddItems()
      33. {
      34. if (dataListView_downloadList.Items.Count > 0)
      35. foreach (DataListView.ListViewItem dItem in dataListView_downloadList.Items) {
      36. dItem.AddControl(DataListView.EmbeddableControl.Progressbar, 1);
      37. pbList.Add((DataListView.ProgressBar)dItem.GetControl(1));
      38. dItem.SubItems.Add("00,00 KB/s");
      39. }
      40. }



      Downloader ProgressChanged Event

      C#-Quellcode

      1. // Downloader ProgressChanged
      2. private void OnProgressChanged(object sender, MultiDownloader.DownloaderEventArgs.ProgressChanged e)
      3. {
      4. int i = ((Downloader)sender).DownloaderIndex;
      5. dataListView_downloadList.Invoke(new MethodInvoker(delegate()
      6. {
      7. dataListView_downloadList.Items[i].SubItems[2].Text = e.DownloadSpeed;
      8. pbList[i].Value = e.ProgressPercentage;
      9. }));
      10. }





      Source Downloader

      EventArgs

      C#-Quellcode

      1. public class DownloaderEventArgs
      2. {
      3. public class ProgressChanged : EventArgs
      4. {
      5. public long BytesReceived { get; private set; }
      6. public int ProgressPercentage { get; private set; }
      7. public long TotalBytesToReceive { get; private set; }
      8. public object UserState { get; private set; }
      9. public string DownloadSpeed { get; private set; }
      10. public ProgressChanged(DownloadProgressChangedEventArgs e, string dlSpeed)
      11. {
      12. BytesReceived = e.BytesReceived;
      13. ProgressPercentage = e.ProgressPercentage;
      14. TotalBytesToReceive = e.TotalBytesToReceive;
      15. UserState = e.UserState;
      16. DownloadSpeed = dlSpeed;
      17. }
      18. }
      19. }



      Downloader Event

      C#-Quellcode

      1. public event EventHandler<DownloaderEventArgs.ProgressChanged> OnProgressChanged;
      2. protected virtual void _ProgressChanged(DownloadProgressChangedEventArgs e, string dlSpeed)
      3. {
      4. if (OnProgressChanged != null) {
      5. OnProgressChanged(this, new DownloaderEventArgs.ProgressChanged(e, dlSpeed));
      6. }
      7. }



      Konstruktor + Destruktor

      C#-Quellcode

      1. public int DownloaderIndex { get; private set; }
      2. // Benötigte Variablen
      3. WebClient webClient;
      4. System.Diagnostics.Stopwatch sw;
      5. public Downloader(string dlUrl, DirectoryInfo savePath, int dlIndex)
      6. {
      7. if (dlUrl != "" && savePath != null)
      8. if (!savePath.Exists)
      9. Directory.CreateDirectory(savePath.FullName);
      10. sw = new System.Diagnostics.Stopwatch();
      11. DownloaderIndex = dlIndex;
      12. DownloadFile(dlUrl, savePath);
      13. }
      14. public void Dispose()
      15. {
      16. GC.SuppressFinalize(this);
      17. }



      Methode DownloadFile()

      C#-Quellcode

      1. private void DownloadFile(string dlURL, DirectoryInfo path)
      2. {
      3. // Download Url aufbereiten
      4. Uri url = dlURL.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || dlURL.StartsWith("https://", StringComparison.OrdinalIgnoreCase) ? new Uri(dlURL) : new Uri("http://" + dlURL);
      5. // DateiNamen ermitteln, Dateipfad wird bei Aufruf von WebClient.DownloadFile erstellt
      6. string[] sUrl = dlURL.Split('/');
      7. // WebClient instanzieren
      8. using (webClient = new WebClient()) {
      9. webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadCompleted);
      10. webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);
      11. sw.Start();
      12. webClient.DownloadFileAsync(url, Path.Combine(path.FullName, sUrl[sUrl.Length - 1]));
      13. }
      14. }



      WebClient Events

      C#-Quellcode

      1. // WebClient -Events
      2. private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e)
      3. {
      4. _ProgressChanged(e, (e.BytesReceived / 1024d / sw.Elapsed.TotalSeconds).ToString("f2")+ " KB/s");
      5. }
      6. private void DownloadCompleted(object sender, AsyncCompletedEventArgs e)
      7. {
      8. sw.Stop();
      9. }


      Dateien
      Die DataListView ist entzwischen mein favorisiertes Steuerelement wenn es um anzeigen von Listen und Arrays geht. Dabei ist mir immer wieder aufgefallen das hin und wieder die Anzeige bzw. die Übersichtlichkeit durch Fehlerberichte beinträchtigt wird. Dieses Problem wird deutlich wenn man z.B. ein Prozess -Array als DataSource der DataListView übergibt.

      Das ganze sah bislang so aus


      Ich habe mich nun entschlossen noch eine Eigenschaft zu ergänzen ErrorReporting damit lässt sich die Fehler -Anzeige regeln.

      ErrorReporting.VeryVerbose


      ErrorReporting.Verbose


      ErrorReporting.Silent



      Ebenso habe ich noch die Progressbar überarbeitet




      *Update*
      Es gibt nun ein weiteres Steuerelement, ein Linien Graph.


      Klassendiagramm



      DataListView_Control.rar [sha256]: DB6A2AE156B69B98BD6B6EF946875902039B6C9E3AF385E6BF0B55A24F974564
      DataListView_Source.rar [sha256]: 4B183C4FBD4AF24FB4F0AB6C08208C2066666BC5FB2F4EC85350F501F21DA586
      Dateien

      Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Fakiz“ ()