当从 ObservableCollection 添加或删除项目时,绑定到 ObservableCollection 的 WP7 UIElement 属性不会更新
在以下代码中:在集合中添加或删除项目时,绑定到 ObservableCollection
的 UIElement
不会更新。
具体来说:
Person 对象包含一个 ObservableCollection 属性 Links,它可以包含任意数量的 Link 对象,这些对象可以引用其他 Person 对象。 Person 和 Link 类都实现了 INotifyPropertyChanged 接口。
public class Person: INotifyPropertyChanged
{
// INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
// fields
private string id = "";
private string firstName = "";
private string lastName = "";
private Links links = new Links();
// properties firing PropertyChanged events
public string ID
{
get { return id; }
set
{
if (value != this.id)
{
this.id = value;
NotifyPropertyChanged("ID");
}
}
}
public string FirstName
{
get { return firstName; }
set
{
if (value != this.firstName)
{
this.firstName = value;
NotifyPropertyChanged("FirstName");
}
}
}
public string LastName
{
get { return lastName; }
set
{
if (value != this.lastName)
{
this.lastName = value;
NotifyPropertyChanged("LastName");
}
}
}
public Links Links
{
get { return links; }
set
{
if (value != this.links)
{
this.links = value;
NotifyPropertyChanged("Links");
}
}
}
// constructors
public Person()
{
new Person("", "", "");
}
public Person(string id, string firstName, string lastName)
{
this.ID = id;
this.FirstName = firstName;
this.LastName = lastName;
}
}
public enum LinkState { none, oneway, twoway }
public class Link: INotifyPropertyChanged
{
// INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
// fields
private Person fromWhom;
private Person toWhom;
// properties firing PropertyChanged events
public Person FromWhom
{
get { return fromWhom; }
set
{
if (value != this.fromWhom)
{
this.fromWhom = value;
NotifyPropertyChanged("FromWhom");
}
}
}
public Person ToWhom
{
get { return toWhom; }
set
{
if (value != this.toWhom)
{
this.toWhom = value;
NotifyPropertyChanged("ToWhom");
}
}
}
// constructors
public Link()
{
new Link(null, null);
}
public Link(Person fromWhom, Person toWhom)
{
this.FromWhom = fromWhom;
this.ToWhom = toWhom;
}
}
Links 和 Crowd 类都是 ObservableCollections 的子类。 Crowd 对象是 Person 对象的 ObservableCollection。 Links 对象是 Link 对象的 ObservableCollection:
public class Links: ObservableCollection<Link>
{
}
public class Crowd : ObservableCollection<Person>
{
}
WP7 应用程序的 MainPage 类是 PhoneApplicationPage 类的子类。 它包含两个属性: Crowd,一个 Crowd 对象和 我,一个 Person 对象。
应显示以下 XAML: a) 从 Me 对象到 Crowd 中的 Person 对象的链接数量,以及 b) Crowd 中的 Person 对象的列表。
<phone:PhoneApplicationPage
x:Name="ThePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PersonLink"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
x:Class="PersonLink.MainPage"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True"
DataContext="{Binding ElementName=ThePage, Path=Crowd}">
<phone:PhoneApplicationPage.Resources>
<local:LinksToCountConverter x:Key="linkCount" />
</phone:PhoneApplicationPage.Resources>
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ElementName=ThePage, Path=Me.FirstName}" />
<TextBlock Text=" has " />
<TextBlock x:Name=LinkCounter Text="{Binding ElementName=ThePage, Path=Me.Links,Converter={StaticResource linkCount}}" />
<TextBlock Text=" links." />
</StackPanel>
<ItemsControl ItemsSource="{Binding .}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ID}" />
<TextBlock Text=" " />
<TextBlock Text="{Binding FirstName}" />
<TextBlock Text=" " />
<TextBlock Text="{Binding LastName}" />
<local:LinkButton Content="Link" Click="LinkButton_Click"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
</phone:PhoneApplicationPage>
但是,当从 Me.Links(ObserverableCollection)添加或删除 Link 对象时,名为“LinkCounter”的 Textblock 不会更新,即使它绑定到 ObservableCollection。
由于 Me.Links ObservableCollection 在添加新链接或删除现有链接时会发生更改,因此我认为与其绑定的任何内容都应该更新。
对于这个问题的任何帮助将不胜感激。 谢谢。
In the following code: a UIElement
bound to an ObservableCollection
does not update when items are added or removed from the collection.
Specifically:
A Person object includes an ObservableCollection
property, Links, which can contain any number of Link objects which can refer to other Person objects.
The Person and Link classes both implement the INotifyPropertyChanged
interface.
public class Person: INotifyPropertyChanged
{
// INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
// fields
private string id = "";
private string firstName = "";
private string lastName = "";
private Links links = new Links();
// properties firing PropertyChanged events
public string ID
{
get { return id; }
set
{
if (value != this.id)
{
this.id = value;
NotifyPropertyChanged("ID");
}
}
}
public string FirstName
{
get { return firstName; }
set
{
if (value != this.firstName)
{
this.firstName = value;
NotifyPropertyChanged("FirstName");
}
}
}
public string LastName
{
get { return lastName; }
set
{
if (value != this.lastName)
{
this.lastName = value;
NotifyPropertyChanged("LastName");
}
}
}
public Links Links
{
get { return links; }
set
{
if (value != this.links)
{
this.links = value;
NotifyPropertyChanged("Links");
}
}
}
// constructors
public Person()
{
new Person("", "", "");
}
public Person(string id, string firstName, string lastName)
{
this.ID = id;
this.FirstName = firstName;
this.LastName = lastName;
}
}
public enum LinkState { none, oneway, twoway }
public class Link: INotifyPropertyChanged
{
// INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
// fields
private Person fromWhom;
private Person toWhom;
// properties firing PropertyChanged events
public Person FromWhom
{
get { return fromWhom; }
set
{
if (value != this.fromWhom)
{
this.fromWhom = value;
NotifyPropertyChanged("FromWhom");
}
}
}
public Person ToWhom
{
get { return toWhom; }
set
{
if (value != this.toWhom)
{
this.toWhom = value;
NotifyPropertyChanged("ToWhom");
}
}
}
// constructors
public Link()
{
new Link(null, null);
}
public Link(Person fromWhom, Person toWhom)
{
this.FromWhom = fromWhom;
this.ToWhom = toWhom;
}
}
The Links and Crowd classes are both subclasses of ObservableCollections. A Crowd object is an ObservableCollection of Person objects. A Links object is an ObservableCollection of Link objects:
public class Links: ObservableCollection<Link>
{
}
public class Crowd : ObservableCollection<Person>
{
}
The MainPage class of the WP7 application is a subclass of the PhoneApplicationPage class.
It contains two properties:
Crowd, a Crowd object and
Me, a Person object.
The following XAML is supposed to display:
a) The number of links from the Me object to the Person objects in the Crowd, and
b) A list of the Person objects in the Crowd.
<phone:PhoneApplicationPage
x:Name="ThePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PersonLink"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
x:Class="PersonLink.MainPage"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True"
DataContext="{Binding ElementName=ThePage, Path=Crowd}">
<phone:PhoneApplicationPage.Resources>
<local:LinksToCountConverter x:Key="linkCount" />
</phone:PhoneApplicationPage.Resources>
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ElementName=ThePage, Path=Me.FirstName}" />
<TextBlock Text=" has " />
<TextBlock x:Name=LinkCounter Text="{Binding ElementName=ThePage, Path=Me.Links,Converter={StaticResource linkCount}}" />
<TextBlock Text=" links." />
</StackPanel>
<ItemsControl ItemsSource="{Binding .}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ID}" />
<TextBlock Text=" " />
<TextBlock Text="{Binding FirstName}" />
<TextBlock Text=" " />
<TextBlock Text="{Binding LastName}" />
<local:LinkButton Content="Link" Click="LinkButton_Click"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
</phone:PhoneApplicationPage>
HOWEVER, when Link objects are added or removed from Me.Links (an ObserverableCollection) the Textblock named "LinkCounter" doesn't update, even though its bound to the ObservableCollection.
Since the Me.Links ObservableCollection is changed when a new Link is added to it, or an existing Link is removed from, I thought that anything bound to it should update.
Any help on this problem would be greatly appreciated.
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
此处不会触发数据绑定,因为您没有更改对 Links 集合的引用。不要绑定到引用并使用转换器,而是尝试使用
The databinding won't be triggered here as you are not changing the reference to the Links collection. Instead of binding to the reference and using a converter try using