INotifyPropertyChanged не запускает PropertyChanged

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

Используя формы Xamarin, я пытаюсь обновить метку при изменении данных объекта.

Соответствующий код:

public new event PropertyChangedEventHandler PropertyChanged;

protected new virtual void OnPropertyChanged(string propertyName)
{
    System.Diagnostics.Debug.WriteLine ("Before");
    if (PropertyChanged != null)
    {
        System.Diagnostics.Debug.WriteLine ("Fired");
        PropertyChanged(this,
            new PropertyChangedEventArgs(propertyName));
    }
}

public string String {
    set { 
        if (_data == value)
            return;
        _data = value;
    OnPropertyChanged ( "String" ); }

    get { return _data; }
}

public new View Content {
        get { 
            label = new Label { Text = String };
            label.SetBinding( Label.TextProperty, new Binding( "String" ) );
            return label;}
    }

По сути, «До» выводится на консоль, а «Уволен» не печатается. Это означает, что PropertyChanged имеет значение null, поэтому PropertyChanged не срабатывает.

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


person Carson    schedule 06.07.2015    source источник
comment
Строка - это ключевое слово, которое может вызывать некоторые проблемы, не могли бы вы изменить его на данные? Кроме того, устанавливаете ли вы контекст привязки на своей странице?   -  person JamesMontemagno    schedule 07.07.2015
comment
Вы создаете привязку, но не устанавливаете BindingContext (по крайней мере, его нет в опубликованном вами примере кода)   -  person Jason    schedule 07.07.2015
comment
SetBinding в свойстве Content не совпадает с установкой контекста привязки?   -  person Carson    schedule 07.07.2015


Ответы (1)


Я не знаю, влияет ли это на это или нет (вероятно, нет), но я бы переписал ваш метод изменения свойства следующим образом.

protected new virtual void OnPropertyChanged(string propertyName)
{
    System.Diagnostics.Debug.WriteLine ("Before");
    var handler = this.PropertyChanged;
    if (handler == null)
    {
        return;
    }

    System.Diagnostics.Debug.WriteLine ("Fired");
    handler(this,
        new PropertyChangedEventArgs(propertyName));
}

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

См. этот ответ на Stackoverflow относительно этого.

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

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

Затем я бы переименовал свойство с String на что-то другое. Я считаю, что реализация платформы .NET в Xamarin включает тип String BCL. Вы можете сбить с толку механизм привязки, хотя он должен быть достаточно умным, чтобы распознать разницу.

Кроме того, убедитесь, что для участника Binding установлено направление Two-Way, а для уведомления об изменении обновления установлено значение PropertyChanged. Это гарантирует, что метод OnPropertyChanged всегда будет запускаться при изменении значения свойства.

new Binding("String")
{
    Mode = BindingMode.TwoWay,
    UpdateSourceTrigger = UpdateSourceTrigger.Explicit,
}
person Johnathon Sullinger    schedule 06.07.2015
comment
Спасибо за комментарий. Я переключился на эти лучшие практики. Грустно сказать, однако, что это не помогло с точки зрения функциональности. PropertyChange все еще не срабатывает. - person Carson; 07.07.2015