我在绑定和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]);
}
}
答案 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 中更改项目时处理问题。