也许我完全不了解事件。
我正在Silverlight中构建一个Windows Phone 7应用程序。
我有UserControl
包裹ListBox
,名为EditableListBox
。 ListBox
有一个数据模板。列表框中的项目由EditableListItem
个对象包装。
数据模板如下:
<DataTemplate>
<Grid ManipulationCompleted="Grid_ManipulationCompleted">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding Path=IconSource}"
Grid.Column="0"
Width="96"
Height="96"
VerticalAlignment="Center"
Visibility="{Binding Path=Editing, Converter={StaticResource visibilityConverter}}"
/>
<TextBlock Text="{Binding Path=Name}" Grid.Column="1" />
</Grid>
</DataTemplate>
我将Visibility
绑定到每个EditableListItem
的属性,因此我需要实现INotifyPropertyChanged
,以便在UI中反映对支持项的更新。 (对吗?或者有更简单的方法吗?)
EditableListItem
:
public class EditableListItem : INotifyPropertyChanged
{
private EditableListBox _parentListBox;
public event PropertyChangedEventHandler PropertyChanged;
public bool Editing
{
get
{
return _parentListBox.Editing;
}
}
public EditableListItem(Section section, EditableListBox parentListBox)
{
_parentListBox = parentListBox;
// after this line, _parentListBox.PropertyChanged is still null.
// why is that?
_parentListBox.PropertyChanged += PropertyChanged;
_parentListBox.PropertyChanged += new PropertyChangedEventHandler(_parentListBox_PropertyChanged);
}
EditableListBox
:
public partial class EditableListBox : UserControl, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
// NotifyPropertyChanged will raise the PropertyChanged event,
// passing the source property that is being updated.
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public void SetSectionsSource(ObservableCollection<Section> sectionsSource)
{
sectionsSource.CollectionChanged += new NotifyCollectionChangedEventHandler(sectionsSource_CollectionChanged);
ContentListBox.ItemsSource = sectionsSource.Select(section => new EditableListItem(section, this) { Enabled = true });
//ContentListBox.ItemsSource.Add(new EditableListItem(new Section("Section", 3)) { Enabled = true });
}
// ...
private bool _editing;
public bool Editing
{
get
{
return _editing;
}
set
{
_editing = value;
NotifyPropertyChanged("Editing");
}
}
}
Editing
属性存储在EditableListBox
- EditableListItem
中,只是转发它。我想直接将EditableListItem.PropertyChanged
附加到EditableListBox.PropertyChanged
,但以下内容不起作用:
// after this line, _parentListBox.PropertyChanged is still null.
// why is that?
_parentListBox.PropertyChanged += PropertyChanged;
以下工作:
_parentListBox.PropertyChanged += new PropertyChangedEventHandler(_parentListBox_PropertyChanged);
这是为什么?第一次尝试是否完全无效(如果是,为什么编译器允许它?)?
答案 0 :(得分:2)
首先,您没有连接PropertyChanged
来实现它。这个想法是WPF使用该事件并将其连接起来。您唯一要做的就是在适用时触发事件。
这是问题的一部分。您拥有Editing
属性,但它没有被触发。我确实理解你已连接父列表框的PropertyChanged
以触发事件,但这不起作用。
如果我理解正确,那么您想要实现的是当列表框的Editing
属性发生变化时,您希望强制列表项的PropertyChanged
。
PropertyChanged
之一是发件人 成为PropertyChanged
所在的对象。这意味着您应该像这样实现它:
public partial class EditableListBox : UserControl, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
// You really should make this protected. You do not want the outside world
// to be able to fire PropertyChanged events for your class.
protected void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private bool _editing;
public bool Editing
{
get
{
return _editing;
}
set
{
_editing = value;
NotifyPropertyChanged("Editing");
}
}
}
public class EditableListItem : INotifyPropertyChanged
{
private EditableListBox _parentListBox;
public EditableListItem(EditableListBox parentListBox)
{
_parentListBox = parentListBox;
_parentListBox.PropertyChanged += new PropertyChangedEventHandler(_parentListBox_PropertyChanged);
}
void _parentListBox_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
// Forward the event.
if (e.PropertyName == "Editing")
NotifyPropertyChanged("Editing");
}
public event PropertyChangedEventHandler PropertyChanged;
// You really should make this protected. You do not want the outside world
// to be able to fire PropertyChanged events for your class.
protected void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public bool Editing
{
get
{
return _parentListBox.Editing;
}
}
}
我不知道你是如何获得对可编辑列表框的引用的,但是假设你通过构造函数得到它。获得引用后,附加列表框的PropertyChanged
事件处理程序。因为,当该对象的Editing
属性发生更改时,实际上您的Editing
属性也会更改。这就是你模拟它的方式。
最后一件事:PropertyChanged
之后null
仍为+= PropertyChanged
的原因是因为对象本身的PropertyChanged
为空。您无法以这种方式连接事件。第二种方法是将事件连接起来的正确方法,上面的例子说明了你对此做了什么。