Au fil des flows

15jan/120

Mettre à jour les donnees dans un controle de type DatagridView

Posted by Fabien Arcellier

A l'origine, je voulais varier les plaisir et publier un billet concernant un code C sous linux utilisant la librairie GTK. Finalement, par manque de temps, j'ai décidé de poster une des notes techniques concernant Winform que j'avais de coté.

C'est quelque chose de déroutant quand on commence à travailler en .NET.

Il n'existe aucune methode sur un composant DataGridView permettant de forcer le composant à recharger sa source de donnée.

Solution simple mais deconseillee

En faite, le controle charge la source de donnée lors de l'affectation de celle ci, si l'objet donne en temps que source a un hash code different. Donc, pour le force à se recharger, il faut changer sa source de donnée par null et lui reaffecter la source precedente

this.DataGridView_MainSplitter_LocksList.DataSource = null;
this.DataGridView_MainSplitter_LocksList.DataSource = this.ListCylindres;

Pourquoi ne pas employer cette methode ?

Le controle DatagridView est construit pour gérer des sources de données assez conséquente. Le mettre entièrement à jour est totalement contre productif. Une lettre qui change dans un mot impliquerait de recharger entièrement ce controle.

Il suffit de penser différemment. En effet, c'est la source de données qui remonte la modification jusqu'au DatagridView.

Une solution plus elegante

Le plus souvent, on utilisera comme source de donnée une classe générique List pour contenir nos données.

public class CylindreList : List<Cylindre>
{
}

Dans le namespace System.ComponentModel, il existe un équivalent BindingList qui possede la particularité d'hériter de la classe BindingSource. Cette classe offre le même service que la classe List. En complément, dès qu'un objet de la liste est modifié, elle émet un évenement indiquant le changement apporté.

public class CylindreList : BindingList<Cylindre>
{
}

Dès qu'un élément est ajouté ou retiré à cette liste de donnée, la DataGridView qui embarque cette source sera mis à jour.

Attention : Si l'objet référencé par une liste est modifiée, la liste ne remontera pas les modifications. Pour faire remonter les modifications, il faut que l'objet implemente l'interface INotifyPropertyChanged : Voir article sur CodeProject.

Remplis sous: Non classé Aucun commentaire
9jan/1215

Donner le focus a un controle PictureBox

Posted by Fabien Arcellier

Je developpai un controle de type PictureBox permettant de sélectionner une zone sur une image. Ce controle doit être utilisable directement dans le designer de visual studio. Il ne doit pas necessiter d'implémenter du code en plus dans la form qui l'héberge pour fonctionner.

Parmi les exigences que je m'etais fixé, il y'avait celle ci :

  • Si l'utilisateur appuie sur Escape, le programme annule la sélection en cours

Au moment de réaliser ce scénario, j'ai eu une petite surprise. Le controle PictureBox dont j'hérite n'est pas un controle focusable. Consequence facheuse, un controle qui ne prend pas le focus ne peut intercepter d'evenement clavier, même quand la propriete KeyPreview de l'objet Form parent est active.

Avec Winform, soit dit en passant, ce n'est pas le seul controle à etre ainsi. Voici une liste tiré de la MSDN sur les controles qui ne peuvent prendre le focus :

  • Panel
  • GroupBox
  • ProgressBar
  • Splitter
  • Label
  • LinkLabel (sans link actif)

Premier réflexe, faire une recherche sur Google à ce sujet (avec les mots PictureBox Winform Focus). J'ai trouvé 2 approches :

  • utiliser un bouton flat à la place d'une PictureBox
  • intercepter les evenements claviers sur la Form et les dispatcher

Comme vous vous en doutez, la deuxième solution n'est pas valable pour résoudre le problème fixée. Pour la première, elle est trop abracadabrante pour sembler être la bonne manière.

Rendre un controle Focusable

J'ai donc creusé un peu plus et j'ai trouvé la propriété ControlStyles qui permet de configurer le comportement d'un controle.

Pour lui permettre de pouvoir obtenir le focus, il suffit de lui affecter la propriété Selectable dans son constructeur :

this.SetStyle(ControlStyles.Selectable, true);

Ca ne suffit pas, à présent, il faut donner au controle le moyen de récupérer le focus. Votre controle même si il peut prendre le focus n'a aucun moyen de le faire.

J'ai trouvé la solution (qui est on ne peut plus evidente à la réflexion) sur le forum de StackOverFlow. Il suffit de demander le focus sur l'appel à la méthode OnMouseDown. C'est à dire lors d'un clic de souris sur votre image.

Voici le code qui résume l'approche :

using System;
using System.Drawing;
using System.Windows.Forms;
 
class SelectablePictureBox : PictureBox {
  public SelectablePictureBox() {
    this.SetStyle(ControlStyles.Selectable, true);
  }
  protected override void OnMouseDown(MouseEventArgs e) {
    this.Focus();
    base.OnMouseDown(e);
  }
}
Remplis sous: Non classé 15 Commentaires