Bound ObservableCollection不会更新ListView

时间:2015-04-08 09:11:21

标签: c# listview windows-phone windows-phone-8.1

我在绑定和INotifyPropertyChanged方面遇到了困难。 我有一个ListView与ObservableCollection绑定,启动时没有问题:数据正确添加到ListView。但是,当我向集合添加新项目时,它不会更新UI。我确定该集合包含该对象,因为我添加了一个按钮来显示该集合的全部内容。

这是我的UI代码:

<StackPanel>
                <Button Content="Show title" Tapped="Button_Tapped"/>
                <ListView ItemsSource="{Binding Subscriptions}">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <Grid>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition Height="*"/>
                                </Grid.RowDefinitions>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto"/>
                                    <ColumnDefinition Width="*"/>
                                </Grid.ColumnDefinitions>
                                <Image Grid.RowSpan="2" Margin="0 0 10 0"
                                    Source="{Binding IconUri.AbsoluteUri}"/>
                                <TextBlock Grid.Column="1"
                                    Text="{Binding Title.Text}" Style="{StaticResource BaseTextBlockStyle}"/>
                                <TextBlock Grid.Row="1" Grid.Column="1"
                                    Text="{Binding LastUpdatedTime.DateTime}"/>
                            </Grid>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </StackPanel>

这是数据上下文类:

class RssReaderData : INotifyPropertyChanged
{
    private string[] acceptContentTypes = {
                                              "application/xml",
                                              "text/xml"
                                          };

    private ObservableCollection<SyndicationFeed> _subscriptions;
    public ObservableCollection<SyndicationFeed> Subscriptions
    {
        get { return _subscriptions; }
        set { NotifyPropertyChanged(ref _subscriptions, value); }
    }

    public int SubscriptionsCount
    {
        get { return Subscriptions.Count; }
    }

    public RssReaderData()
    {
        Subscriptions = new ObservableCollection<SyndicationFeed>();
        AddFeedAsync(new Uri("http://www.theverge.com/rss/index.xml"));
        AddFeedAsync(new Uri("http://blogs.microsoft.com/feed/"));
    }

    public async Task<bool> AddFeedAsync(Uri uri)
    {
        // Download the feed at uri
        HttpClient client = new HttpClient();
        var response = await client.GetAsync(uri);

        // Check that we retrieved the resource without error and that the resource has XML content
        if (!response.IsSuccessStatusCode || !acceptContentTypes.Contains(response.Content.Headers.ContentType.MediaType))
            return false;

        var xmlFeed = await response.Content.ReadAsStringAsync();

        // Create a new SyndicationFeed and load the XML to it
        SyndicationFeed newFeed = new SyndicationFeed();
        newFeed.Load(xmlFeed);

        // If the title hasn't been set, the feed is invalid
        if (String.IsNullOrEmpty(newFeed.Title.Text))
            return false;

        Subscriptions.Add(newFeed);
        return true;
    }

    #region INotifyPropertyChanged management
    public event PropertyChangedEventHandler PropertyChanged;
    public void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    public bool NotifyPropertyChanged<T> (ref T variable, T value, [CallerMemberName] string propertyName = null)
    {
        if (object.Equals(variable, value)) return false;
        variable = value;
        NotifyPropertyChanged(propertyName);
        return true;
    }
    #endregion
}

正如你所看到的,我实现了INotifyPropertyChanged接口,而我认为我甚至不需要(ObservableCollection为我做了这个)。我不关心通知我添加到我的集合中的项目的更改,我需要的是在添加新项目时通知。

我会说我的代码没问题,但似乎没有,我不明白为什么: - /

另外,虽然我很喜欢,但我有两个简单的问题:ListView和ListBox之间以及Grid和GridView之间的区别是什么?

谢谢你的帮助: - )

编辑:根据要求,这是页面的代码隐藏

 RssReaderData context = new RssReaderData();

    public FeedsPage()
    {
        this.InitializeComponent();

        this.NavigationCacheMode = NavigationCacheMode.Required;
    }

    private async void Button_Tapped(object sender, TappedRoutedEventArgs e)
    {
        string feedsTitles = "\n";
        foreach (var feed in context.Subscriptions)
        {
            feedsTitles += "\n " + feed.Title.Text;
        }

        MessageDialog d = new MessageDialog("There are " + context.SubscriptionsCount + " feeds:" + feedsTitles);
        await d.ShowAsync();
    }

    private async void NewFeedSubscribeButton_Tapped(object sender, TappedRoutedEventArgs e)
    {
        string feedUri = NewFeedUriInput.Text;
        if (String.IsNullOrEmpty(feedUri))
            return;

        if (!Uri.IsWellFormedUriString(feedUri, UriKind.Absolute))
        {
            MessageDialog d = new MessageDialog("The URL you entered is not valid. Please check it and try again.", "URL Error");
            await d.ShowAsync();
            return;
        }

        bool feedSubscribed = await context.AddFeedAsync(new Uri(feedUri));
        if (feedSubscribed)
        {
            NewFeedUriInput.Text = String.Empty;
            FeedsPivot.SelectedIndex = 0;
        }
        else
        {
            MessageDialog d = new MessageDialog("There was an error fetching the feed. Are you sure the URL is referring to a valid RSS feed?", "Subscription error");
            await d.ShowAsync();
            return;
        }
    }

    private void FeedsList_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (FeedsList.SelectedIndex > -1 && FeedsList.SelectedIndex < context.SubscriptionsCount)
        {
            Frame.Navigate(typeof(FeedDetailsPage), context.Subscriptions[FeedsList.SelectedIndex]);
        }
    }

1 个答案:

答案 0 :(得分:1)

原来你创建了两个 RssReaderData 的实例 - 一个在代码后面,一个在xaml中:

<Page.DataContext> 
     <DataModel:RssReaderData/> 
</Page.DataContext

在这种情况下, ListView 所绑定的集合与您在后面的代码中引用的集合不同 - context

简单的解决方案可能是从XAML中删除上面的行并在后面的代码中设置 DataContext

public FeedsPage()
{
    this.InitializeComponent();
    this.NavigationCacheMode = NavigationCacheMode.Required;
    this.DataContext = context;
}

另一种情况是它也可能无法正确更新UI,as KooKiz has pointed out - 最好首先创建项目,然后将其添加到集合中。

您还可以查看at this question and its answers,在 ObservableCollection 中更改项目时处理问题。