简体   繁体   中英

Xamarin IsVisible is not dynamically updated when binded to a getter property

I'm trying to dynamically update an element's visibility by binding IsVisible to a getter property. However, the IsVisible does not automatically change the UI unless I refresh the page.

The following is the code snippet:

xaml:

<StackLayout>
    <Picker Title="Choose..." ItemsSource="{Binding MyItemOptions}" SelectedItem="{Binding MyItem}"/>
    <Label Text="MyItem is Milk" IsVisible="{Binding Path=IsMilkItem}"/>
</StackLayout>

C#:

private string _myItem;
public string MyItem
{
    get => _myItem;
    set
    {
        SetValue(ref _myItem, value);
    }
}

public bool IsMilkItem
{
    get { return MyItem == "Milk"; }
}




public event PropertyChangedEventHandler PropertyChanged;

protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

protected bool SetValue<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
    bool response = false;
    if (field == null ||
        !field.Equals(value))
    {
        field = value;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        response = true;
    }
    return response;
}

The boolean property is updated in code after updating MyItem. However, the UI element does not automatically show up until i manually re-render the page.

I will be grateful if someone has a solution to this.

when you change the value of MyItem , it does not raise a PropertyChanged event for IsMilkItem , so the UI is never told to update

public string MyItem
{
    get => _myItem;
    set
    {
        SetValue(ref _myItem, value);
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsMilkItem"));

    }
}

According to your description, you want to choose item from picker, when selecting item is Milk, you want to Label control is visible, Am I right?

If yes, I modify your code, you can take a look:

public partial class Page17 : ContentPage, INotifyPropertyChanged
{

    public ObservableCollection<string> MyItemOptions { get; set; }
    private string _MyItem;
    public string MyItem
    {
        get { return _MyItem; }
        set
        {
            _MyItem = value;
            if(_MyItem== "Milk")
            {
                IsMilkItem = true;
            }
            else
            {
                IsMilkItem = false;
            }
        }
    }
    private bool _IsMilkItem;
    public bool IsMilkItem
    {
        get { return _IsMilkItem; }
        set
        {
            _IsMilkItem = value;
            RaisePropertyChanged("IsMilkItem");
        }
    }

    public Page17 ()
    {
        InitializeComponent ();
        MyItemOptions = new ObservableCollection<string>()
        {
            "item 1",
            "item 2",
            "item 3",
            "Milk"
        };
        this.BindingContext = this;
    }

    public event PropertyChangedEventHandler PropertyChanged;


    public void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Update:

You can use Label trigger to set label isvisible, and don't need to IsMilkItem property to set Lable Isvisible.

<Picker x:Name="picker1" Title="Choose..." ItemsSource="{Binding MyItemOptions}" SelectedItem="{Binding MyItem}" />
        <Label Text="MyItem is Milk" IsVisible="False" >
            <Label.Triggers>
                <DataTrigger TargetType="Label" Binding="{Binding Source={x:Reference picker1},Path=SelectedItem}" Value="Milk">
                    <Setter Property="IsVisible"
                Value="True"/>
                </DataTrigger>
            </Label.Triggers>
        </Label>

Here is the .cs:

public ObservableCollection<string> MyItemOptions { get; set; }
    private string _MyItem;
    public string MyItem
    {
        get { return _MyItem; }
        set
        {
            _MyItem = value;

        }
    }


    public Page17 ()
    {
        InitializeComponent ();
        MyItemOptions = new ObservableCollection<string>()
        {
            "item 1",
            "item 2",
            "item 3",
            "Milk"
        };
        this.BindingContext = this;
    }

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM