代码之家  ›  专栏  ›  技术社区  ›  Nick Heiner

.NET:事件处理困难

  •  2
  • Nick Heiner  · 技术社区  · 14 年前

    也许我不完全理解事件。

    我正在Silverlight中构建一个WindowsPhone7应用程序。

    我有一个 UserControl 包裹着 ListBox ,调用 EditableListBox . 这个 列表框 有一个数据模板。列表框中的项由 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 每个人的财产 可编辑列表项 ,所以我需要实施 INotifyPropertyChanged 因此,对备份项的更新将反映在UI中。(对吧?或者有更简单的方法吗?)

    可编辑列表项 :

    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);
        }
    

    可编辑列表框 :

    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 属性存储在 可编辑列表框 - 可编辑列表项 就往前走。我想加入 EditableListItem.PropertyChanged EditableListBox.PropertyChanged 直接,但以下方法不起作用:

      // after this line, _parentListBox.PropertyChanged is still null.
      // why is that?
      _parentListBox.PropertyChanged += PropertyChanged;
    

    以下方法确实有效:

    _parentListBox.PropertyChanged += new PropertyChangedEventHandler(_parentListBox_PropertyChanged);
    

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

    1 回复  |  直到 14 年前
        1
  •  2
  •   Pieter van Ginkel    14 年前

    首先,你不需要 PropertyChanged 实施它。其思想是WPF使用该事件并将其连接起来。你唯一要做的就是在合适的时候触发事件。

    这也是问题的一部分。你有 Editing 但它没有被解雇。我知道你已经把 财产变更 启动事件的父列表框,但这不起作用。

    如果我的想法是正确的,你想要完成的是 编辑 列表框的属性被更改,您需要 财产变更 要强制的列表项的。

    其中一件事 财产变更 是寄件人吗 成为 财产变更 位于。这意味着您应该这样实现它:

    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;
            }
        }
    }
    

    我不知道如何获得对可编辑列表框的引用,但假设是通过构造函数获得的。当你得到推荐信时,你会附上 财产变更 列表框的事件处理程序。因为,当 编辑 这个对象的属性实际上改变了 编辑 属性也会更改。你就是这样模拟的。

    最后一件事:为什么 财产变更 仍然 null 之后 += PropertyChanged 是因为 财产变更 对象本身为空。你不能用这种方式连接事件。第二种方法是连接事件的正确方法,上面的示例演示了如何处理这个问题。