【问题标题】:Custom ItemsSource property for a UserControlUserControl 的自定义 ItemsSource 属性
【发布时间】:2012-03-16 15:09:41
【问题描述】:

有人知道如何自定义ItemsSource吗?

我想做的是为我自己的UserControl创建一个itemsSource,以便它可以被ObservableCollection<>绑定。

另外,我可以知道每当itemsSource中的项目数更新,以便做进一步的程序。

非常感谢。

【问题讨论】:

    标签: wpf data-binding itemssource


    【解决方案1】:

    您可能需要在您的控件中执行类似的操作

    public IEnumerable ItemsSource
    {
        get { return (IEnumerable)GetValue(ItemsSourceProperty); }
        set { SetValue(ItemsSourceProperty, value); }
    }
    
    public static readonly DependencyProperty ItemsSourceProperty =
        DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(UserControl1), new PropertyMetadata(new PropertyChangedCallback(OnItemsSourcePropertyChanged)));
    
    private static void OnItemsSourcePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        var control = sender as UserControl1;
        if (control != null)
            control.OnItemsSourceChanged((IEnumerable)e.OldValue, (IEnumerable)e.NewValue);
    }
    
    
    
    private void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)
    {
        // Remove handler for oldValue.CollectionChanged
        var oldValueINotifyCollectionChanged = oldValue as INotifyCollectionChanged;
    
        if (null != oldValueINotifyCollectionChanged)
        {
            oldValueINotifyCollectionChanged.CollectionChanged -= new NotifyCollectionChangedEventHandler(newValueINotifyCollectionChanged_CollectionChanged);
        }
        // Add handler for newValue.CollectionChanged (if possible)
        var newValueINotifyCollectionChanged = newValue as INotifyCollectionChanged;
        if (null != newValueINotifyCollectionChanged)
        {
            newValueINotifyCollectionChanged.CollectionChanged += new NotifyCollectionChangedEventHandler(newValueINotifyCollectionChanged_CollectionChanged);
        }
    
    }
    
    void newValueINotifyCollectionChanged_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        //Do your stuff here.
    }
    

    【讨论】:

    • newValueINotifyCollectionChanged 始终是null。
    • 当我清除有界列表时,不会触发 OnItemsSourcePropertyChanged...应该是吗?
    【解决方案2】:

    在您的 CustomControl 中使用 DependencyProperty ItemsSource,然后绑定到此 DependencyProperty

    这是 XAML 代码(识别 ListBox 的 DataContext):

    <UserControl
        x:Name="MyControl">
        <ListBox
            DataContext="{Binding ElementName=MyControl}"
            ItemsSource="{Binding ItemsSource}">
        </ListBox>
    </UserControl>
    

    这是代码隐藏:

    public partial class MyCustomControl
    {
        public IEnumerable ItemsSource
        {
            get { return (IEnumerable)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }
    
        public static readonly DependencyProperty ItemsSourceProperty =
            DependencyProperty.Register("ItemsSource", typeof(IEnumerable),
                typeof(ToolboxElementView), new PropertyMetadata(null));
    }
    

    这是代码,您可以在其中使用“MyCustomControl”:

    <Window>
        <local:MyCustomControl
            ItemsSource="{Binding MyItemsIWantToBind}">
        </local:MyCustomControl>
    </Window>
    

    【讨论】:

      【解决方案3】:

      简化答案。

          public IEnumerable ItemsSource
          {
              get => (IEnumerable)GetValue(ItemsSourceProperty);
              set => SetValue(ItemsSourceProperty, value);
          }
      
          public static readonly DependencyProperty ItemsSourceProperty =
              DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(UserControl1), new PropertyMetadata(null, (s, e) =>
              {
                  if (s is UserControl1 uc)
                  {
                      if (e.OldValue is INotifyCollectionChanged oldValueINotifyCollectionChanged)
                      {
                          oldValueINotifyCollectionChanged.CollectionChanged -= uc.ItemsSource_CollectionChanged;
                      }
      
                      if (e.NewValue is INotifyCollectionChanged newValueINotifyCollectionChanged)
                      {
                          newValueINotifyCollectionChanged.CollectionChanged += uc.ItemsSource_CollectionChanged;
                      }
                  }
              }));
      
          private void ItemsSource_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
          {
              // Logic Here
          }
      
          // Do Not Forget To Remove Event On UserControl Unloaded
          private void UserControl1_Unloaded(object sender, RoutedEventArgs e)
          {
              if (ItemsSource is INotifyCollectionChanged incc)
              {
                  incc.CollectionChanged -= ItemsSource_CollectionChanged;
              }
          }
      

      【讨论】:

        猜你喜欢
        • 2010-12-04
        • 1970-01-01
        • 1970-01-01
        • 2019-12-08
        • 1970-01-01
        • 2014-08-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多