Связанное с данными числовое нисходящее «скрывающее» исключение, брошенное в связанное свойство - PullRequest
1 голос
/ 03 марта 2009

У меня проблема с тем, что исключение, генерируемое из средства доступа к набору свойств, не перехватывается моим глобальным обработчиком исключений.

У меня возникла проблема в более крупном приложении, и после большого скрежета зубов я решил проблему и попытался повторить проблему в более простом проекте.

Ниже приведен код и поведение. Может кто-нибудь объяснить это поведение, пожалуйста, и как мне правильно написать код для достижения желаемого результата, за исключением того, что глобальный обработчик событий перехватит исключение.

//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;
    }

}

Если я установлю точку останова в строке 'throw new ArgumentNullException', программа непременно сломается в этой точке, когда я изменю значение элемента управления numericUpDown (который связан со свойством NumberOfWheels). Однако это единственный способ определить, было ли выброшено исключение. Через интерфейс пользователя не выводится сообщение о том, что генерируется исключение, т. Е. Оно не перехватывается глобальным обработчиком исключений.

В отличие от этого, если я изменяю значение свойства с помощью нажатия кнопки, то обработчик генерирует исключение И перехватывает его с отображаемым окном сообщения.

Чего мне не хватает?

Ответы [ 2 ]

0 голосов
/ 04 марта 2009

Спасибо, Муфака

Это было очень полезно и позволило мне расширить свои знания в области привязки данных. Однако исключение все еще не перехватывается глобальным обработчиком исключений. Код разрывается в последнем '}' binding_BindingComplete, и отображается «ArgumentNullException не обработан кодом пользователя».

Единственный способ заставить его работать, как вы описываете, - это установить

binding.FormattingEnabled = false;

но, похоже, у него есть свои проблемы.

Я думаю, что сейчас я сделаю ваш подход, но вместо того, чтобы снова вызвать исключение, я выведу окно сообщения и восстановлю исходное значение.

private void binding_BindingComplete(object sender, BindingCompleteEventArgs e)
{
   if (e.BindingCompleteState == BindingCompleteState.Exception)
   {
       MessageBox.Show(e.Exception.Message);
       e.Binding.ReadValue(); //resets value to actual value of data source instead of leaving it as changed value of control
   }
}

Вероятно, я могу использовать этот обработчик для всех элементов управления с привязкой к данным.

0 голосов
/ 03 марта 2009

Привязка «проглотит» или «скроет» исключение. Это, по-видимому, должно быть более отказоустойчивым.

Вам необходимо прослушать событие BindingComplete и проверить BindingCompleteState в свойстве BindingCompleteEventArgs BindingCompleteState. Если это значение BindingCompleteState.Exception, то свойство BindingCompleteEventArgs Exception будет содержать исключение, которое было сгенерировано.

    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;
        }
    }
...