Как добавить событие PropertyChanged для свойства? - PullRequest
0 голосов
/ 26 июня 2019

Я создал различные свойства внутри пользовательского элемента управления и добился большого успеха в доступе к ним и их редактировании. Сейчас я пытаюсь настроить события для ряда из них, которые будут вызваны при изменении одного из этих свойств. Я попробовал пример кода MSDN для этого ( см. Здесь ), но он выдает мне эту ошибку, когда я пытаюсь построить решение:

Код серьезности Описание Состояние подавления строки файла проекта Ошибка CS0079 Событие AbilityScoreDisplay.AbilityTitleChanged может появляться только в левой части листа символов + = или - = DnD C: \ Users \ bradley beasley \ Documents \ Visual Studio 2019 \ Projects \ Таблица символов DnD \ Таблица символов DnD \ AbilityScoreDisplay.Designer.cs 199 Активно

Другая проблема, с которой я сталкиваюсь, заключается в том, что я пытаюсь выяснить, как заставить это событие появляться в окне свойств конструктора Visual Studio 2019.

Вот код, который я добавил в файл конструктора:

namespace DnD_Character_Sheet
{
    partial class AbilityScoreDisplay : UserControl
    {
        public string AbilityTitle
        {
            get
            {
                return AbiltyTitleLabel.Text;
            }
            set
            {
                AbiltyTitleLabel.Text = value;
                Invalidate();
            }
        }
        public int AbilityModifier
        {
            get
            {
                return Convert.ToInt32(AbilityModifierTextBox.Text);
            }
            private set
            {
                if (value >= 0) AbilityModifierTextBox.Text = String.Format("+{0}", value);
                else AbilityModifierTextBox.Text = value.ToString();
                Invalidate();
            }
        }
        public int AbilityScore
        {
            get
            {
                return Convert.ToInt32(AbilityScoreLabel.Text);
            }
            set
            {
                AbilityModifier = (int)(Math.Floor((double)(value) / 2)) - 5;
                Invalidate();
            }
        }

        private EventHandler onAbilityTitleChanged { get; set; }
        private EventHandler onAbilityScoreChanged { get; set; }

        public event EventHandler AbilityTitleChanged
        {
            add
            {
                onAbilityTitleChanged += value;
            }
            remove
            {
                onAbilityTitleChanged -= value;
            }
        }
        public event EventHandler AbilityScoreChanged
        {
            add
            {
                onAbilityScoreChanged += value;
            }
            remove
            {
                onAbilityScoreChanged -= value;
            }
        }

        protected virtual void OnAbilityTitleChanged(EventArgs e)
        {
            AbilityTitleChanged?.Invoke(this, e);
        }
        protected virtual void OnAbilityScoreChanged(EventArgs e)
        {
            AbilityScoreChanged?.Invoke(this, e);
        }
    }
}

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

Любая помощь будет принята с благодарностью :)

Ответы [ 2 ]

5 голосов
/ 26 июня 2019

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

Во-первых, вы должны иметь возможность отслеживать обработчики событий:

private EventHandler _onAbilityTitleChanged; 

Вы выставляете это событие через открытое свойство:

public event EventHandler AbilityTitleChanged
{
    add
    {
        _onAbilityTitleChanged += value;
    }
    remove
    {
        _onAbilityTitleChanged -= value;
    }
}

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

public string AbilityTitle
{
    get
    {
        return AbiltyTitleLabel.Text;
    }
    set
    {
        AbiltyTitleLabel.Text = value;
        //Raising the event!
        _onAbilityTitleChanged?.Invoke(this, new EventArgs());
    }
}

Другие классы могут затем подписаться на ваше событие:

var control = new AbilityScoreDisplay();
control.AbilityTitleChanged += SomeHandlerForWhenTitleChanges;

private void SomeHandlerForWhenTitleChanges(object sender, EventArgs e)
{
    //....
}

Возможно, вы захотите немного прочитать о *Интерфейс 1015 * INotifyPropertyChanged .

2 голосов
/ 26 июня 2019

Обычно вы делаете это путем реализации INotifyPropertyChanged.Это позволяет использовать одно событие для всех свойств.Имя свойства передается в аргументах события.

partial class AbilityScoreDisplay : UserControl, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    ...
}

В свойствах это делается (на примере AbilityModifier):

private int _abilityModifier;
public int AbilityModifier
{
    get { return _abilityModifier; }
    private set {
        if (value != _abilityModifier) {
            _abilityModifier = value;
            AbilityModifierTextBox.Text = value >= 0
                ? String.Format("+{0}", value)
                : value.ToString();
            OnPropertyChanged(nameof(AbilityModifier));
        }
    }
}

Предполагается, что этот обработчик событий

private void ScoreDisplay_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    ...
}

Вы можете подписать событие на

PropertyChanged += ScoreDisplay_PropertyChanged;

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


Вы можете использовать INotifyPropertyChanged вместе с привязкой данных к немедленнообновлять пользовательский интерфейс при внесении изменений в данные.Для этого вы должны создать класс со свойствами и реализацией INotifyPropertyChanged.Затем в форме вы назначаете экземпляр этого класса DataSource из BindingSource.Затем элементы управления привязываются к этому BindingSource.

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

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