【问题标题】:View is not getting refreshed in bindable layout xamarin forms视图未在可绑定布局 xamarin 表单中刷新
【发布时间】:2019-05-03 15:35:38
【问题描述】:

我通过在堆栈视图中使用可绑定布局来创建类别的水平列表,如下图所示,所以当我单击我的一个类别时,我想更改文本颜色,但实际上绑定不会更新视图在属性更改后被解雇。

                <StackLayout x:Name="CategoryStack" BindableLayout.ItemsSource="{Binding CategoryListItems,Mode=TwoWay}"
         Orientation="Horizontal" Padding="5,3,0,3" BackgroundColor="Transparent">
                    <BindableLayout.ItemTemplate>
                        <DataTemplate >
                            <custom:PancakeView BackgroundColor="White"  Grid.Row="0" Grid.Column="0" IsClippedToBounds="true" Padding="4" HeightRequest="47"  CornerRadius="5">
                                <Grid>
                                    <Label HorizontalTextAlignment="Center" Margin="0" VerticalOptions="Center" FontSize="Small"  Text="{Binding Name}" TextColor="{Binding NameColor,Mode=TwoWay}">

                                    </Label>
                                </Grid>


                                <custom:PancakeView.GestureRecognizers>
                                    <TapGestureRecognizer  CommandParameter="{Binding .}" Command="{Binding Path=BindingContext.CategoryTappedCmd,Source={x:Reference CategoryStack}}"  NumberOfTapsRequired="1" />
                                </custom:PancakeView.GestureRecognizers>

                            </custom:PancakeView>



                        </DataTemplate>
                    </BindableLayout.ItemTemplate>
                </StackLayout>

下面是我的 ViewModel 代码

  public class ProductsListViewModel : ViewModelBase
    {

    private ObservableCollection<SpicesCategory> _CategoryListItems = new ObservableCollection<SpicesCategory>();

    public ObservableCollection<SpicesCategory> CategoryListItems
    {
        get => _CategoryListItems;
        set
        {
            _CategoryListItems = value;
            RaisePropertyChanged(() => (CategoryListItems));
        }
    }

  public ICommand CategoryTappedCmd => new Command(CategoryTapped);

    public async void CategoryTapped(object obj)
    {


        SpicesCategory SelectedspicesCategory = obj as SpicesCategory;

        foreach (var item in CategoryListItems)
        {
            if(item == SelectedspicesCategory)
            {
                item.IsSelected = true;

                item.NameColor = Color.Red;
            }
            else
            {
                item.IsSelected = false;
                item.NameColor = Color.Black;
            }

        }

    }
 }

下面是我的 SpicesCategory 模型

public  class SpicesCategory
{
    public long Id { get; set; }
    public string Name { get; set; }

    public bool IsSelected { get; set; }

    public Color NameColor { get; set; }
}

下面是我的 ViewModelBase 继承 ExtendedBindableObject

 public class ViewModelBase : ExtendedBindableObject
  {

    public ViewModelBase(INavigationService navigationService)
    {

    }

    private bool _isBusy;

    public event PropertyChangedEventHandler PropertyChanged;

    public bool IsBusy
    {
        get => _isBusy;
        set
        {
            _isBusy = value;
            RaisePropertyChanged(() =>(IsBusy));
        }
    }

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

    public virtual Task InitializeAsync(object data)
    {
        return Task.FromResult(false);
    }
}

下面是我继承BindableObject的ExtendedBindableObject

 public abstract class ExtendedBindableObject : BindableObject
{
    public void RaisePropertyChanged<T>(Expression<Func<T>> property)
    {
        var name = GetMemberInfo(property).Name;
        OnPropertyChanged(name);
    }



    private MemberInfo GetMemberInfo(Expression expression)
    {
        MemberExpression operand;
        LambdaExpression lambdaExpression = (LambdaExpression)expression;
        if (lambdaExpression.Body as UnaryExpression != null)
        {
            UnaryExpression body = (UnaryExpression)lambdaExpression.Body;
            operand = (MemberExpression)body.Operand;
        }
        else
        {
            operand = (MemberExpression)lambdaExpression.Body;
        }
        return operand.Member;
    }
}

【问题讨论】:

  • 在 SpicesCategory 类上实现 INotifyPropertyChanged
  • @MaxHampton 嗨,我实际上正在使用 RaisePropertyChanged,请检查上面的代码现在是否已更新。
  • 我看到您在 ViewModel 类上实现了 INotifyPropertyChanged,但您没有将文本颜色绑定到 ViewModel 上的属性,而是绑定到 SpicesCategory 上的属性。在这种情况下,您需要来自包含您要绑定的属性的类的属性更改通知。更改应该从您设置 item.Name 和 item.NameColor 的 foreach 循环触发
  • 好的,我在 foreach 循环之后尝试了这个 ObservableCollection NewCategory = new ObservableCollection();新类别 = 类别列表项; CategoryListItems = new ObservableCollection(); CategoryListItems = 新类别;但它不起作用,问题是我的 UI 部分没有更新,我的模型正在获取更新的值
  • 您只需要 SpicesCategory : BindableObject 和设置器中的 RaisePropertyChanged

标签: mvvm xamarin.forms


【解决方案1】:

你能给我一个例子如何在 RaisePropertyChanged 二传手。

尝试将您的 SpicesCategory 模型更改为:

public class SpicesCategory :ExtendedBindableObject
{
    public long Id { get; set; }

    public bool IsSelected { get; set; }

    private string _name { get; set; }

    public string Name
    {
        get => _name;
        set
        {
            _name = value;
            RaisePropertyChanged(() => (Name));
        }
    }

    private Color _nameColor { get; set; }

    public Color NameColor
    {
        get => _nameColor;
        set
        {
            _nameColor = value;
            RaisePropertyChanged(() => (NameColor));
        }
    }
}

【讨论】:

  • 感谢它现在的工作,只是想知道为什么它没有从我的 ViewModel 中得到改变,因为它正在继承 > ViewModelBase 和 ViewModelBase 正在继承 > ExtendedBindableObject 所以它应该从我的 viewModel 和我的代码中更新非常适合列表视图,只是在某些情况下不起作用。
  • 当你设置一个绑定时,你告诉你的视图,注意事件 PropertyChanged 在持有你绑定的属性的对象上触发。该页面具有视图模型的绑定上下文,但例如列表视图的每个单元格都具有绑定到列表视图项目源的集合中对象的绑定上下文。单元格内的绑定然后监视 PropertyChanged 在这些对象上触发,而不是在视图模型类上
猜你喜欢
  • 2020-02-29
  • 2019-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 2019-08-17
相关资源
最近更新 更多