2009-03-03 3 views
1

Je rencontre un problème lorsqu'une exception renvoyée depuis un accesseur de jeu de propriétés n'est pas interceptée par mon gestionnaire d'exceptions global. J'ai eu le problème dans une plus grande application et après beaucoup de grincements de dents dépannant le problème que j'ai essayé, et réussi à reproduire le problème dans un projet plus simple.Databound numericupdown 'hidden' exceptiong thrown dans la propriété bound

Voici le code et le comportement. Quelqu'un peut-il expliquer ce comportement s'il vous plaît et comment je devrais coder correctement pour atteindre le résultat souhaité, qui est que l'exception soit interceptée par le gestionnaire d'événements global.

//Program.cs - Wire up global exception handling 
static class Program 
{ 
[STAThread] 
static void Main() 
{ 
    Application.EnableVisualStyles(); 
    Application.SetCompatibleTextRenderingDefault(false); 

    Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException); 
    Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); 

    Application.Run(new Form1()); 
} 

static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) 
{ 
    MessageBox.Show("Exception occured : " + e.Exception.Message); 
} 

*

//In main form create instance of class containing bound property and setup databinding 
//to numericUpDown control 
private void Form1_Load(object sender, EventArgs e) 
{ 
    _car = new Car(); 
    _car.NumberOfWheels = 4; 
    numericUpDown1.DataBindings.Add(new Binding("Value", _car, "NumberOfWheels", true, DataSourceUpdateMode.OnPropertyChanged)); 
} 

*

public int NumberOfWheels 
{ 
    get { return _numberOfWheels; } 
    set 
    { 
     if (value < 4) 
      //Throw some exception 
      throw new ArgumentNullException("Argument null exception trigger in Number Of Wheels property"); 

     _numberOfWheels = value; 
    } 

}

Si je mets un point d'arrêt à la ligne 'throw new ArgumentNullException' le programme va certainement briser à ce moment où Je change la valeur du contrôle numericUpDown (qui est lié à la propriété NumberOfWheels). Cependant, c'est le seul moyen de détecter si l'exception est levée. Aucun message n'est affiché via l'interface utilisateur indiquant que l'exception est levée, c'est-à-dire qu'elle n'est pas interceptée par le gestionnaire d'exceptions global. En revanche, si je modifie la valeur de la propriété via un clic de bouton, l'exception est levée et interceptée par mon gestionnaire, avec une boîte de message affichée.

Qu'est-ce qui me manque?

Répondre

0

La liaison "avale" ou "masque" l'exception. Ceci est, probablement, d'être plus tolérant aux fautes.

Vous devez écouter l'événement BindingComplete et vérifier BindingCompleteState sur la propriété BindingCompleteEventArgs BindingCompleteState. Si cette valeur est BindingCompleteState.Exception, la propriété BindingCompleteEventArgs Exception contiendra l'exception qui a été levée.

public Form1() 
    { 
     InitializeComponent(); 

     Binding binding = new Binding("Value", _car, "NumWheels", true, DataSourceUpdateMode.OnPropertyChanged); 
     numericUpDown1.DataBindings.Add(binding); 
     binding.BindingComplete += new BindingCompleteEventHandler(binding_BindingComplete); 

    } 

    void binding_BindingComplete(object sender, BindingCompleteEventArgs e) 
    { 
     if (e.BindingCompleteState == BindingCompleteState.Exception) 
     { 
      throw e.Exception; 
     } 
    } 
0

Merci Mufaka

Cela a été très utile et m'a permis d'élargir mes connaissances plus loin databinding. Toutefois, l'exception n'est toujours pas interceptée par le gestionnaire d'exceptions global. Le code se rompt au dernier '}' de binding_BindingComplete et "ArgumentNullException n'a pas été manipulé par le code utilisateur" est affiché.

La seule façon que je peux le faire fonctionner comme vous le décrivez est si je mis

binding.FormattingEnabled = false; 

mais cela semble avoir ses propres problèmes.

Je pense que ce que je vais faire pour le moment est de prendre votre approche mais au lieu de relancer l'exception, je vais afficher une boîte de message et restaurer la valeur d'origine.

Je peux probablement utiliser ce gestionnaire pour tous les contrôles de base de données.