在 Xamarin 和 MVVM 中绑定 ObservableCollection Listview 时不刷新特定标签

Not Refreshing Spesific Label While Binding ObservableCollection Listview in Xamarin & MVVM

public class Zicker : INotifyPropertyChanged
{
    public class MyClass
    {
        public string HeyName { get; set; }
        public string HeySurname { get; set; }
        public int HeyAge { get; set; }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged([CallerMemberName] string name = null)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }

    private ObservableCollection<MyClass> _yourList = new ObservableCollection<MyClass>();
    public ObservableCollection<MyClass> YourList
    {
        get
        {
            return _yourList;
        }
        set
        {
            _yourList = value;
            RaisePropertyChanged("YourList");
            RaisePropertyChanged("BindMeLabel");
        }
    }

    public int BindMeLabel
    {
        get { return _yourList.Sum(a => a.HeyAge); }
    }

    public void WonCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        RaisePropertyChanged("BindMeLabel");
    }

    public List<string> heresamplenames = new List<string> { "Mohamed", "Zaran", "Ivan" };
    public List<string> heresamplesurnames = new List<string> { "Pakou", "Simmone", "Zagoev" };
    public List<int> heresampleages = new List<int> { 17,33,50 };

    public Zicker()
    {
        ObservableCollection<MyClass> vs = new ObservableCollection<MyClass>();
        for (int i = 0; i < 3; i++)
        { vs.Add(new MyClass { HeyName = heresamplenames[i], HeySurname = heresamplesurnames[i], HeyAge = heresampleages[i] }); }
        YourList = vs; YourList.CollectionChanged += WonCollectionChanged;
    }
}

<ContentPage.Content>
    <StackLayout Orientation="Vertical" HorizontalOptions="Center" VerticalOptions="Center">
        <ContentView HorizontalOptions="Fill" VerticalOptions="Fill">
            <ListView HorizontalOptions="Center" VerticalOptions="Center" HasUnevenRows="True" ItemsSource="{Binding YourList}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <ViewCell.View>
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="1*"></ColumnDefinition>
                                        <ColumnDefinition Width="1*"></ColumnDefinition>
                                        <ColumnDefinition Width="1*"></ColumnDefinition>
                                    </Grid.ColumnDefinitions>
                                    <Label HorizontalTextAlignment="Center" VerticalTextAlignment="Center" Text="{Binding Path=HeyName}" Grid.Column="0" FontSize="12" TextColor="Black"></Label>
                                    <Label HorizontalTextAlignment="Center" VerticalTextAlignment="Center" Text="{Binding Path=HeySurname}" FontSize="12" TextColor="Black" Grid.Column="1"/>
                                    <Entry HorizontalTextAlignment="Center" VerticalOptions="Center" Text="{Binding Path=HeyAge}" FontSize="12" Keyboard="Numeric" TextColor="Black" Grid.Column="2"/>
                                </Grid>
                            </ViewCell.View>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </ContentView>
        <Label Text="{Binding BindMeLabel}" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" FontSize="40" TextColor="Black"></Label>
    </StackLayout>
</ContentPage.Content>

        public MainPage()
    {
        InitializeComponent();
        BindingContext = new Zicker();
    }

我的问题:在此列表中,有三个名字、姓氏和年龄。在底部,还有一个标签,应该显示为年龄集合的总和。

当 UI 启动时,Label 运行良好。但是,如果我尝试更改任何年龄条目,绑定标签就会出现大问题。

我想使用 MVVM 结构,但由于这个问题,标签绑定刚启动就可以工作。

如果您正在更新 HeyName 属性,绑定不会更新,因为 class MyClass 没有实现 INotifyPropertyChanged.

尝试用以下代码替换 MyClass class:

public class MyClass : INotifyPropertyChanged
{
    private string name;
    private string surname;
    private int age;

    public string HeyName
    {
        get => name;
        set
        {
            name = value;
            RaisePropertyChanged("HeyName");
        }
    }

    public string HeySurname
    {
        get => surname;
        set
        {
            surname = value;
            RaisePropertyChanged("HeySurname");
        }
    }

    public int HeyAge
    {
        get => age;
        set
        {
            age = value;
            RaisePropertyChanged("HeyAge");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged([CallerMemberName] string name = null)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }
}

编辑:

抱歉,当您更新 HeyAge 属性 时不会调用 CollectionChanged,因为只有在更改集合时才会调用它,但 不会 当集合中某项的 属性 更改时。

尝试将 OnAgeChanged 事件添加到 class MyClass 并在 HeyAge 属性 更改时调用它:

public class MyClass : INotifyPropertyChanged
{
    public event EventHandler OnAgeChanged;

    public int HeyAge
    {
        get => age;
        set
        {
            age = value;
            RaisePropertyChanged("HeyAge");
            OnAgeChanged?.Invoke(this, EventArgs.Empty);
        }
    }
    ...
    ...

然后,当您将新的 MyClass 对象添加到集合中时,像这样在 ViewModel 中注册事件:

public Zicker()
{
    ObservableCollection<MyClass> vs = new ObservableCollection<MyClass>();
    for (int i = 0; i < 3; i++)
    {
        var test = new MyClass()
        {
            HeyName = heresamplenames[i],
            HeySurname = heresamplesurnames[i],
            HeyAge = heresampleages[i],
        };
        test.OnAgeChanged += Test_OnAgeChanged;
        vs.Add(test);
    }

    YourList = vs;
    YourList.CollectionChanged += WonCollectionChanged;
}

private void Test_OnAgeChanged(object sender, EventArgs e)
{
    RaisePropertyChanged("BindMeLabel");
}

请注意,WonCollectionChanged 它不再是必需的。 另请注意,不需要变量 vs,您可以直接在 YourList 对象中工作。