改变ObservableCollection的属性什么都不做

时间:2017-01-21 01:20:57

标签: mvvm xamarin binding observablecollection

在我的Xamarin项目中,我有一个ListView,它由一个ObservableCollection填充,它包含具有一些属性的“Item”对象。如果我向集合添加项目,UI会更新,但如果我只更改了一个属性,它就不会做任何事情。即使通过添加项目进行UI更新也没有做任何事情,尽管属性得到了正确的更改。如果属性发生变化,如何刷新UI?

BindableBase是一个来自PRISM的类,它实现了INotifyPropertyChanged,而DelegateCommand实现了ICommand,顺便说一句。

这是我的XAML:

<ListView ItemsSource="{Binding ListItems}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell x:Name="viewCell">
                    <ContentView Padding="0,0,0,5" 
                                     HeightRequest="50">
                        <ContentView.GestureRecognizers>
                            <TapGestureRecognizer BindingContext="{Binding Source={x:Reference listView}, Path=BindingContext}"
                                                         Command="{Binding ItemTappedCommand}" 
                                                         CommandParameter="{Binding Source={x:Reference viewCell}, Path=BindingContext}" />
                        </ContentView.GestureRecognizers>
                        <Frame OutlineColor="{Binding Color}" Padding="8">
                            <StackLayout Orientation="Horizontal" >
                                <Image x:Name="checkedImage"
                                         HeightRequest="30"
                                         WidthRequest="30"
                                         BackgroundColor="{Binding Color}"
                                         />
                                <Label Text="{Binding Text}" 
                                         TextColor="{Binding Color}" 
                                         Margin="20,0,0,0"
                                         VerticalTextAlignment="Center" 
                                         HorizontalOptions="FillAndExpand"/>
                                <Image Source="{Binding Image}" />
                            </StackLayout>
                        </Frame>
                    </ContentView>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

这是我的ViewModel:

public class DetailPageViewModel : BindableBase
{
    public DetailPageViewModel()
    {
        _listItems.Add(new ViewModels.Item("#123456", "Test1", "XamarinForms.Assets.Yellow.png"));
        _listItems.Add(new ViewModels.Item("#654321", "Test3", "XamarinForms.Assets.close.png"));
    }

    private ObservableCollection<Item> _listItems = new ObservableCollection<Item>();

    public ObservableCollection<Item> ListItems
    {
        get { return _listItems; }
        set { SetProperty(ref _listItems, value); }
    }

    public DelegateCommand<Item> ItemTappedCommand => new DelegateCommand<Item>(ItemTapped);

    private void ItemTapped(Item listItem)
    {
// Adding an item refreshes the UI.

        _listItems.Add(new ViewModels.Item("#654321", "Test3", "XamarinForms.Assets.close.png"));

// But changing the color of an item does nothing. Not even after an UI refresh.

        _listItems.ElementAt(_listItems.IndexOf(listItem)).Color="#987654";
    }
}

我的Item类:

    public class Item
{
    public string Color {  set; get; }
    public ImageSource Check { set; get; }
    public string Text { private set; get; }
    public ImageSource Image { private set; get; }


    public Item(string color, string text, string imageSource)
    {
        Check = ImageSource.FromResource("XamarinForms.Assets.checkmark-outlined-verification-sign.png");

        Color = color;
        Text = text;
        Image = ImageSource.FromResource(imageSource);
    }

}

1 个答案:

答案 0 :(得分:2)

这是因为您的item类还需要实现INotifyPropertyChanged。在您使用Prism的情况下,您只需要使您的item类扩展BindableBase(已经为您实现INotifyPropertyChanged的Prism基类)。

链接:https://github.com/PrismLibrary/Prism/blob/a60d38013c02b60807e9287db9ba7f7506af0e84/Source/Prism/Mvvm/BindableBase.cs

这应该有效。

我也看到你在做这件事:

public ObservableCollection<Item> ListItems
{
    get { return _listItems; }
    set { SetProperty(ref _listItems, value); }
}

使用ObservableCollections,您不需要手动引发事件,因为它们已在内部执行。它们可以定义为常规属性。

public ObservableCollection<Item> ListItems {get; set;}