【问题标题】:Databinding problem in Xamarin.Forms CollectionViewXamarin.Forms CollectionView 中的数据绑定问题
【发布时间】:2020-09-12 04:42:06
【问题描述】:

我找不到使用 Xamarin.Forms 中的 CollectionView 更改列表内对象属性的好方法。

下面是我的代码(为了便于阅读,只写了相关代码)。

我有一个列表,我正在将其数据绑定到 CollectionView。集合视图中的每个条目都包含一个带有数字的标签和两个用于将该数字加减 1 的按钮。

请注意,下面的代码运行良好。但是,我对模型中的 INotifyPropertyChanged 实现并不满意,它应该只是一个简单的 DTO。我想从我的模型中删除这个接口以及 OnPropertyChanged。当我这样做时,当我点击一个按钮时,带有数字的标签不再改变。

所以我应该在 ViewModel 中进行这些更改,但我无法弄清楚如何进行。在视图模型中实现这一点的合适方法是什么,这样我就可以只用一个简单的属性来保持我的模型干净?

请注意,BaseViewModel 已经实现了 INotifyPropertyChanged 接口。

Xaml:

<CollectionView ItemsSource="{Binding MyList}" SelectionMode="Single">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <StackLayout Orientation="Horizontal">
                <Button Text="-"
                        Command="{Binding Source={x:Reference MyPage}, Path=BindingContext.QuantityMinusCommand}"
                        CommandParameter="{Binding .}" />
                <Label Text="{Binding Quantity, Mode=TwoWay}" />
                <Button Text="+"
                        Command="{Binding Source={x:Reference MyPage}, Path=BindingContext.QuantityPlusCommand}"
                        CommandParameter="{Binding .}" />
            </StackLayout>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

视图模型:

public class CollectionViewModel : BaseViewModel
{
    private List<MyObject> _myList = new List<MyObject>();

    public ICommand QuantityMinusCommand { get; }
    public ICommand QuantityPlusCommand { get; }

    public CollectionViewModel()
    {
        QuantityMinusCommand = new Command(OnQuantityMinusCommand);
        QuantityPlusCommand = new Command(OnQuantityPlusCommand);
    }

    public List<MyObject> MyList
    {
        get => _myList;
        set
        {
            _myList = value;
            OnPropertyChanged("MyList");
        }
    }

    private void OnQuantityMinusCommand(object o)
    {
        var myObject = (MyObject)o;
        myObject.Quantity = --myObject.Quantity;
    }


    private void OnQuantityPlusCommand(object o)
    {
        var myObject = (MyObject)o;
        myObject.Quantity = ++myObject.Quantity;
    }
}

型号:

public class MyObject : System.ComponentModel.INotifyPropertyChanged
{
    private int _quantity;
    public int Quantity
    {
        get => _quantity;
        set
        {
            _quantity = value;
            OnPropertyChanged("Quantity");
        }
    }


    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
    {
        var changed = PropertyChanged;
        if (changed == null)
            return;

        changed.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
    }
}

【问题讨论】:

  • nuget Fody.PropertyChanged 可以将 PropertyChanged 行为注入到您的 DTO 中,而无需将实现显式添加到类中

标签: c# xamarin.forms data-binding


【解决方案1】:

您的 BaseViewModel 可以继承 INotifyPropertyChanged。然后你的模型可以是一个简单的 DTO。

public class BaseViewModel : ObservableObject
{
    public BaseViewModel()
    {

    }

    bool isBusy = false;
    public bool IsBusy
    {
        get { return isBusy; }
        set { SetProperty(ref isBusy, value); }
    }
}

还有 ObservableObject

/// <summary>
/// Observable object with INotifyPropertyChanged implemented
/// </summary>
public class ObservableObject : INotifyPropertyChanged
{
    protected bool SetProperty<T>(ref T backingStore, T value,
        [CallerMemberName]string propertyName = "",
        Action onChanged = null)
    {
        if (EqualityComparer<T>.Default.Equals(backingStore, value))
            return false;

        backingStore = value;
        onChanged?.Invoke();
        OnPropertyChanged(propertyName);
        return true;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        var changed = PropertyChanged;
        if (changed == null)
            return;

        changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

而模型可以是这样的:

public class MyObject
{
    public int Quantity { get; set; }
}

视图模型:

public class CollectionViewModel : BaseViewModel
{
    // ...
}

【讨论】:

    猜你喜欢
    • 2022-01-11
    • 2020-11-09
    • 1970-01-01
    • 1970-01-01
    • 2022-01-06
    • 2016-09-25
    • 1970-01-01
    • 2018-02-17
    • 1970-01-01
    相关资源
    最近更新 更多