【问题标题】:Not Refreshing Spesific Label While Binding ObservableCollection Listview in Xamarin & MVVM在 Xamarin 和 MVVM 中绑定 ObservableCollection Listview 时不刷新特定标签
【发布时间】:2018-11-25 15:06:51
【问题描述】:
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();
    }

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

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

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

【问题讨论】:

    标签: c# xamarin xamarin.forms binding observablecollection


    【解决方案1】:

    如果您要更新HeyName 属性,绑定不会更新,因为MyClass 类没有实现INotifyPropertyChanged。

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

    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 事件添加到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 对象中工作。

    【讨论】:

    • 我正在更新 HeyAge 属性,那么这些更改对 MyClass 是否足够?绑定 BindMeLabel 应该是 HeyAge 属性的总和。
    • 我已经编辑了我的答案,请参阅编辑部分。希望对您有所帮助。
    猜你喜欢
    • 2019-07-13
    • 2016-08-05
    • 2016-04-25
    • 2013-09-18
    • 2021-07-21
    • 2018-01-21
    • 2018-08-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多