C# .NET:事件难度

C# .NET:事件难度,c#,.net,silverlight,events,C#,.net,Silverlight,Events,也许我不完全理解事件 我正在Silverlight中构建Windows Phone 7应用程序 我有一个UserControl,它包装了一个名为EditableListBox的ListBox。列表框有一个数据模板。列表框中的项目由EditableListItem对象包装 数据模板如下所示: <DataTemplate> <Grid ManipulationCompleted="Grid_ManipulationCompleted"> <Gri

也许我不完全理解事件

我正在Silverlight中构建Windows Phone 7应用程序

我有一个
UserControl
,它包装了一个名为
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>
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");
        }
    }

}
以下方面确实起了作用:

_parentListBox.PropertyChanged += new PropertyChangedEventHandler(_parentListBox_PropertyChanged);

为什么会这样?第一次尝试是否完全无效(如果是,编译器为什么允许它?

首先,您没有连接
属性changed
来实现它。其思想是WPF使用该事件并将其连接起来。您要做的唯一一件事就是在适用时触发事件

这也是问题的一部分。您有
编辑
属性,但它没有被激发。我知道您已连接父列表框的
属性changed
,以触发事件,但这不起作用

如果我的想法是正确的,那么您想要完成的是,当列表框的
编辑
属性发生更改时,您希望强制更改列表项的
属性

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;
        }
    }
}
我不知道如何获得对可编辑列表框的引用,但假设通过构造函数获得它。获取引用后,将附加listbox的
PropertyChanged
事件处理程序。因为,当对象的
编辑
属性更改时,实际上,您的
编辑
属性也会更改。这就是你模拟的方式


最后一件事:
PropertyChanged
+=PropertyChanged
之后仍然是
null
的原因是对象本身的
PropertyChanged
为null。不能以这种方式连接事件。第二种方法是将事件关联起来的正确方法,上面的示例显示了如何处理这些事件。

感谢您的详细回复。那么,
eventA+=eventB
实际上是做什么的呢?我不太确定。从逻辑上讲,它会将附加到
eventB
的所有事件句柄复制到
eventA
,但我对此表示怀疑,因为不可能从类外部访问事件的内容。我得做些测试。至少我以前没用过。
_parentListBox.PropertyChanged += new PropertyChangedEventHandler(_parentListBox_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;
        }
    }
}