I'm having difficulty with events. I'm building a Windows Phone 7 app.
I have a few classes that implement an editable list box, that can switch into editing mode and let the user add or remove items.
EditableListBox.xaml
and the code behind is the wrapper around the ListBox
.
EditableListBoxController<T>
is the class that controls the behavior. I made it generic for greater type safety, although that means that I need to break it into a separate class instead of implementing the functionality in EditableListBox.xaml.cs
, which is kind of a pain.
EditableListItem
is a single item in the list. It wraps the items that are being added or removed, and is responsible for knowing if that item belongs in the list, if the "edit" icon should be displayed, etc.
EditableListBox.xaml:
<Grid x:Name="LayoutRoot">
<ListBox x:Name="ContentListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid ManipulationCompleted="Grid_ManipulationCompleted">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding IconSource}"
Grid.Column="0"
Width="96"
Height="96"
VerticalAlignment="Center"
Visibility="{Binding Editing, Converter={StaticResource visibilityConverter}}"
/>
<TextBlock Text="{Binding Name}"
Grid.Column="1"
Foreground="{Binding Enabled, Converter={StaticResource enabledConverter}}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
In the data template, the editing icon binds to EditableListItem.Editing
:
public bool Editing
{
get
{
return _parentListController.Editing;
}
}
EditableListItem.Editing
binds to EditableListBoxController<T>.Editing
:
private bool _editing;
public bool Editing
{
get
{
return _editing;
}
set
{
_editing = value;
NotifyPropertyChanged("Editing");
refreshItemsSource();
}
}
EditableListItem
implements INotifyPropertyChanged
, so it can update the UI appropriately. It liste开发者_运维技巧ns to PropertyChanged
on the parent controller, so it can update Editing
when it needs to:
private EditableListBoxController<T> _parentListController;
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public EditableListItem(T item, EditableListBoxController<T> parentListController)
{
_parentListController = parentListController;
_parentListController.PropertyChanged += PropertyChanged;
_parentListController.PropertyChanged += new PropertyChangedEventHandler(_parentListBox_PropertyChanged);
this.ContainedItem = item;
}
void _parentListBox_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
{
PropertyChanged(sender, e);
}
}
The EditableListItem
's constructor is called here:
private void refreshItemsSource()
{
if (_sectionsSource == null)
{
return;
}
_editableListBox.ContentListBox.ItemsSource = (from section in _sectionsSource
where Editing || section.Enabled
select new EditableListItem<T>(section, this)).ToList();
}
For some reason, however, this doesn't work. When I change the controller's Editing
property, the PropertyChanged
event handler is null. Thus, the event doesn't get fired. This is odd, because I step through in the debugger and see that the EditableListItem<T>
is registering its event handler, yet somehow it appears to have been deregistered later?
What am I doing wrong here?
The problem is probably that you are binding to EditableListItem.Editing and no event is being raised to indicate this is changing, only that the underlying property of the EditableListBoxController
is changing, but this is not being monitored by the ListBox
Off the top of my head I would say that you should have EditableListItem
implement INotifyPropertyChanged
. Then the EditableListItem
should wire it self to the PropertyChange event of the EditableListBoxController
.
When the controller fires the event the EditableListItem
will handle the event and fire it's own PropertyChanged' event indicating that the
Editing` property has changed.
精彩评论