【发布时间】:2015-04-08 09:11:21
【问题描述】:
我在绑定和 INotifyPropertyChanged 方面遇到困难。 我有一个绑定到 ObservableCollection 的 ListView,并且在启动时没有问题:数据已正确添加到 ListView。但是,当我向集合中添加新项目时,它不会更新 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]);
}
}
【问题讨论】:
-
我发现您的代码没有明显错误。您能否显示向集合中添加新项目的代码部分?
-
当然,我编辑了我的消息以包含我在 AddFeedAsync 方法中省略的代码。这是我实际将对象添加到 ObservableCollection 的地方。
-
换一种方式:填充您的项目,然后添加到列表中。
var newFeed = new SyndicationFeed(); newFeed.Load(xmlFeed); Subscriptions.Add(newFeed);我的理论是您的项目已正确添加到列表中,但显示为空项目,因为SyndicationFeed类未实现INotifyPropertyChanged。如果我的理论是正确的,那么这个简单的更改应该可以修复您的应用。 -
您的代码对我来说也很好。你能分享代码隐藏文件中的代码吗?另外(只是确保),您是否尝试过调试它,您是否 100% 确定到达并成功执行了
Subscriptions.Add(newFeed);行? -
@Jeahel xaml 中的这一行是指两个不同的 RssReaderData 类。尝试在您的 Page 构造函数中添加这一行:
this.DataContext = context;,从 xaml 中删除 DataContext 并检查是否有帮助。
标签: c# listview windows-phone windows-phone-8.1