【问题标题】:Xamarin IsVisible is not dynamically updated when binded to a getter propertyXamarin IsVisible 在绑定到 getter 属性时不会动态更新
【发布时间】:2020-03-28 16:42:01
【问题描述】:

我正在尝试通过将 IsVisible 绑定到 getter 属性来动态更新元素的可见性。但是,除非我刷新页面,否则 IsVisible 不会自动更改 UI。

以下是sn-p的代码:

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;
}

更新 MyItem 后,布尔属性在代码中更新。但是,在我手动重新渲染页面之前,UI 元素不会自动显示。

如果有人对此有解决方案,我将不胜感激。

【问题讨论】:

    标签: c# xaml xamarin mvvm xamarin.forms


    【解决方案1】:

    当您更改 MyItem 的值时,它不会为 IsMilkItem 引发 PropertyChanged 事件,因此永远不会通知 UI 更新

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

    【讨论】:

    • 我的函数 SetValue() 实际上已经引发了 PropertyChanged 事件
    • SetValue 在“MyItem”上调用 PropertyChanged。它不会在“IsMilkItem”上调用 PropertyChanged,这是您遇到问题的属性
    【解决方案2】:

    根据您的描述,您想从选择器中选择项目,选择项目是牛奶时,您想要标记控件是可见的,我是对的吗?

    如果是,我修改你的代码,你可以看看:

    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));
            }
        }
    }
    

    更新:

    您可以使用Label trigger来设置标签是否可见,并且不需要IsMilkItem属性来设置标签是否可见。

    <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>
    

    这是.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;
        }
    

    【讨论】:

    • @YIFAN,如果我的回复对你有帮助,请记得标记我的回复,谢谢。
    • 您好 Cherry,感谢您的回复。这是我过去的做法。但是,我觉得除了编写一些额外的代码行来设置布尔值之外,肯定还有其他方法可以做到这一点。就像 knockout.js(也使用 MVVM 模式)具有 Computed Observables 一样,Xamarin 中是否有任何计算的 observable 值可以自动触发 UI?
    • @YIFAN,另一种方法是使用Trigger,请看我的更新。
    猜你喜欢
    • 2023-03-09
    • 2020-12-01
    • 2019-12-14
    • 2020-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-19
    相关资源
    最近更新 更多