Может ли «PropertyChanged Event» связываемого поведения Xamarin напрямую обрабатывать свойство его представления? - PullRequest
0 голосов
/ 24 января 2020

Я хочу обработать свойства представления с привязываемым поведением.

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

Изменение "AssociatedObject" "to stati c вызывает проблемы с привязкой.

Что мне делать?

public class CustNameBehavior : Behavior<Label>
{
    public Label AssociatedObject { get; private set; }

    public static readonly BindableProperty MyNameProperty = BindableProperty.Create(nameof(MyName), typeof(string), typeof(CustNameBehavior), null, BindingMode.OneWay, propertyChanged: OnMyNameChanged);
    private static void OnMyNameChanged(BindableObject bindable, object oldValue, object newValue)
    {
        CustNameBehavior target = (CustNameBehavior)bindable;

        if (target != null)
        {
            var value = (string)newValue;

            if (string.IsNullOrWhiteSpace(value))
            {
                AssociatedObject.Text = "Empty!";   => this is inaccessible. because of non static.
            }
            else
            {
                AssociatedObject.Text = value;   => this is inaccessible. because of non static.
            }
        }
    }

    protected override void OnAttachedTo(Label bindable)
    {
        base.OnAttachedTo(bindable);
        AssociatedObject = bindable;
        bindable.BindingContextChanged += Bindable_BindingContextChanged;
    }

    protected override void OnDetachingFrom(Label bindable)
    {
        base.OnDetachingFrom(bindable);
        bindable.BindingContextChanged -= Bindable_BindingContextChanged;
        AssociatedObject = null;
    }

    private void Bindable_BindingContextChanged(object sender, EventArgs e)
    {
        base.OnBindingContextChanged();
        BindingContext = AssociatedObject.BindingContext;
    }

    public string MyName
    {
        get => (string)GetValue(MyNameProperty);
        set
        {
            SetValue(MyNameProperty, value);
        }
    }
}

1 Ответ

1 голос
/ 24 января 2020

Обработчик OnMyNameChanged должен быть stati c, потому что MyNameProperty слишком (ну, возможно, это технически возможно, но это было бы хрупко и прыгало через обручи). В любом случае, вы бы хотели, чтобы AssociatedObject не был статическим c, потому что вам нужен один на каждый экземпляр CustNameBehavior, все остальное, скорее всего, не будет работать должным образом.

Однако вы может обращаться к нестационарным c методам и свойствам из OnMyNameChanged, поскольку экземпляр CustNameBehavior передается через параметр bindable. Кроме того, этот экземпляр содержит ссылку на Label через AssociatedObject. Следовательно, вы можете получить доступ к AssociatedObject через target (bindable, который уже был приведен к CustNameBehavior), следовательно, ваш метод станет

private static void OnMyNameChanged(BindableObject bindable, object oldValue, object newValue)
{
    CustNameBehavior target = (CustNameBehavior)bindable;

    if (target != null && target.AssociatedObject != null)
    {
        var value = (string)newValue;

        if (string.IsNullOrWhiteSpace(value))
        {
            target.AssociatedObject.Text = "Empty!"; 
        }
        else
        {
            target.AssociatedObject.Text = value;
        }
    }
}

Обратите внимание, что Я добавил проверку для AssociatedObject, являющегося null, потому что я предполагаю, что OnMyNameChanged вызывается до того, как поведение будет связано.

ИМХО, было бы еще лучше, если бы вы переместили экземпляр logi c в метод самостоятельно

private static void OnMyNameChanged(BindableObject bindable, object oldValue, object newValue)
{
    CustNameBehavior target = (CustNameBehavior)bindable;
    target?.SetLabelName((string)newValue);
}

private void SetLabelName(string name)
{
    if(AssociatedObject != null)
    {
        AssociatedObject.Text = string.IsNullOrEmpty(name) ? "Empty!" : name;
    }
}

Кроме того, вам нужно будет установить AssociatedObject.Text из OnAttachedTo, поскольку MyNameProperty не будет установлен в настоящее время, что приведет к тому, что AssociatedObject.Text не будет обновлено. Вы можете использовать SetLabelName для этой цели, таким образом, вам не нужно будет дублировать логи c, которые проверяют наличие пустой строки.

protected override void OnAttachedTo(Label bindable)
{
    base.OnAttachedTo(bindable);
    AssociatedObject = bindable;
    SetLabelName((string)GetValue(MyNameProperty));
    bindable.BindingContextChanged += Bindable_BindingContextChanged;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...