WINFORM или WPF: как вызвать пользовательское событие внутри конструктора класса, который его генерирует - PullRequest
3 голосов
/ 19 декабря 2010

У меня есть userControl11 (в winform или wpf), который имеет пользовательское событие ValueChanged.Если я помещу его в клиентскую форму и в form_load установлю его значение равным 100, это вызовет событие ValueChanged.Но если я установлю это значение внутри конструктора UserControl1, пользовательское событие не сработает.Как я могу заставить это сделать это?

независимо от технической причины, функционально это имеет смысл.Если объект инициализирует свое значение из некоторых источников, неизвестных клиентской форме, и у клиентской формы есть текстовое поле, привязанное к этому значению usercontrol, несомненно, что он может обновить свое текстовое поле в любое время, в том числе, когда форма загружается только с использованием одногообработчик события.Без этого клиентская форма должна создать другой инициализатор для этого связанного текстового поля при загрузке формы.

Ниже исходного кода моих испытаний в winform:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace test
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void userControl11_ValueChanged()
        {
            MessageBox.Show(userControl11.Value.ToString());
        }

        private void Form1_Load(object sender, EventArgs e)
        {
           // This will trigger ValueChanged Event
            userControl11.Value = 100;
        }
    }
}



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace customevent
{
    [DefaultEvent("ValueChanged")]
    public partial class UserControl1 : UserControl
    {
        private int m_value;

        public delegate void ValueChangedHandler();
        [Category("Action")]
        [Description("Value changed.")]
        public event ValueChangedHandler ValueChanged;

        public int Value
        {
            get { return m_value; }
            set { 
                m_value = value;
                if (ValueChanged != null)
                {
                    ValueChanged();
                }
            }
        }

        public UserControl1()
        {
            InitializeComponent();
            // this won't trigger ValueChanged Event
            this.Value = 100;
        }
        public UserControl1(int iValue)
        {
            this.Value = iValue;
            InitializeComponent();
        }

    }
}

Ответы [ 4 ]

3 голосов
/ 19 декабря 2010

Из класса вы можете использовать On Events.

На события защищены, поэтому вы не можете вызвать их из формы хостинга, но из класса вы можете вызвать их. (если вы хотите вызвать их вручную из-за пределов запроса, вам нужно предоставить их с помощью специального метода.)

public UserControl1(IEnumerable<Action> subscribers)   {

   this.OnValueChanged(new EventArgs());
   this.Value = 100;
}

Прочитайте о конкретном событии, которое вы вызываете, и отправьте ему соответствующие EventArgs. События On - это методы, которые вызывают события. События On защищены, вы можете их перегрузить, просто не забудьте использовать базовую функцию в конце.

Edit:

В соответствии с Event Design в MSDN, каждое событие имеет соответствующий метод OnEvent (то же имя с префиксом On). Эти методы используются для поднятия базовых событий.

Передаваемые EventArgs совпадают с событием с тем же именем, поэтому, если вы хотите увидеть передаваемые аргументы, прочитайте описание MSDN действительного события.

Я бы предложил просто подписаться на событие и использовать точки останова, чтобы посмотреть, как выглядят EventArgs.

3 голосов
/ 19 декабря 2010

Разница в том, что в конструкторе ни один подписчик не имеет возможности присоединиться к событию.Form_Load вызывается только при отображении элемента управления, поэтому есть возможность подписаться на него между конструкцией и отображением.

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

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

  public UserControl1(IEnumerable<Action> subscribers)
  {
        InitializeComponent();

        this.ValueChanged += () => 
           {
               foreach(var subcriber in subscribers)
                    subscriber();
           } 

        this.Value = 100;
  }
1 голос
/ 19 декабря 2010

Это довольно естественное следствие установки значения в конструкторе . По замыслу конструктор класса инициализирует начальное состояние объекта. Ничего не изменилось, только когда вы присваиваете свойство, событие Changed не должно вызываться. Как написано, мероприятие действительно поднимается, у кого-то просто еще нет возможности подписаться на него. Это работает случайно, вам действительно нужно назначить член m_value.

Так что, если форма интересуется значением по умолчанию свойства, то она должна просто прочитать его обратно. Вы также можете вызвать метод userControl11_ValueChanged () напрямую, например, чтобы воспользоваться его побочными эффектами.

Если вы хотите всегда генерировать событие с хорошими шансами, что подписчик увидит его, назначьте свойство в переопределении метода OnLoad в UserControl (или в событии Load).

0 голосов
/ 19 декабря 2010

Вызывать события в конструкторе на самом деле не имеет смысла (если это не статическое событие): поскольку объект еще не полностью инициализирован, ни у какого другого объекта еще не было возможности подписаться на событие ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...