Binding to Children.Count

后端 未结 2 1040
名媛妹妹
名媛妹妹 2021-01-20 01:01

I\'m using a binding of the form

{Binding RelativeSource={RelativeSource Self}, Path=Children.Count, Converter={StaticResource CountToDimensionConverter}, C         


        
相关标签:
2条回答
  • 2021-01-20 01:19
    public class GridEx : Grid, INotifyPropertyChanged
    {
        public delegate void ChildrenUpdatedEventHandler(DependencyObject visualAdded, DependencyObject visualRemoved);
    
        public event ChildrenUpdatedEventHandler ChildrenUpdated;
        public event PropertyChangedEventHandler PropertyChanged;
    
        public bool HasChildren => Children.Cast<UIElement>().Where(element => element != null).Count() > 0;
        public int ChildCount => Children.Cast<UIElement>().Where(element => element != null).Count();
    
        protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved)
        {
            base.OnVisualChildrenChanged(visualAdded, visualRemoved);
    
            ChildrenUpdated?.Invoke(visualAdded, visualRemoved);
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(HasChildren)));
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ChildCount)));
        }
    }
    

    Use property ChildCount instead.

    0 讨论(0)
  • 2021-01-20 01:26

    That's because UIElementCollection (the type of the Children property) doesn't raise notifications when a new item is added or removed, so the binding isn't refreshed

    You could, however, create your own custom UniformGrid, and override the CreateUIElementCollection property to create an instance of a custom collection that inherits UIElementCollection and implements INotifyCollectionChanged.

    Here's a basic implementation :

    ObservableUIElementCollection

    public class ObservableUIElementCollection : UIElementCollection, INotifyCollectionChanged, INotifyPropertyChanged
    {
        public ObservableUIElementCollection(UIElement visualParent, FrameworkElement logicalParent)
            : base(visualParent, logicalParent)
        {
        }
    
        public override int Add(UIElement element)
        {
            int index = base.Add(element);
            var args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, element, index);
            OnCollectionChanged(args);
            OnPropertyChanged("Count");
            OnPropertyChanged("Item[]");
            return index;
        }
    
        public override void Clear()
        {
            base.Clear();
            OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
            OnPropertyChanged("Count");
            OnPropertyChanged("Item[]");
        }
    
        public override void Insert(int index, UIElement element)
        {
            base.Insert(index, element);
            var args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, element, index);
            OnCollectionChanged(args);
            OnPropertyChanged("Count");
            OnPropertyChanged("Item[]");
        }
    
        public override void Remove(UIElement element)
        {
            int index = IndexOf(element);
            if (index >= 0)
            {
                RemoveAt(index);
                var args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, element, index);
                OnCollectionChanged(args);
                OnPropertyChanged("Count");
                OnPropertyChanged("Item[]");
            }
        }
    
        public override UIElement this[int index]
        {
            get
            {
                return base[index];
            }
            set
            {
                base[index] = value;
                var args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, value, index);
                OnCollectionChanged(args);
                OnPropertyChanged("Item[]");
            }
        }
    
        public event NotifyCollectionChangedEventHandler CollectionChanged;
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
        {
            var handler = CollectionChanged;
            if (handler != null)
                handler(this, e);
        }
    
        protected virtual void OnPropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    

    MyUniformGrid

    public class MyUniformGrid : UniformGrid
    {
        protected override UIElementCollection CreateUIElementCollection(FrameworkElement logicalParent)
        {
            return new ObservableUIElementCollection(this, logicalParent);
        }
    }
    

    XAML

    <local:MyUniformGrid x:Name="MyUniformGrid"
         Rows="{Binding RelativeSource={RelativeSource Self}, Path=Children.Count, Converter={StaticResource CountToDimensionConverter}, ConverterParameter=R}"
         Columns="{Binding RelativeSource={RelativeSource Self}, Path=Children.Count, Converter={StaticResource CountToDimensionConverter}, ConverterParameter=C}">
        <Button Content="Hello, World!" />
        <Button Content="Hello, World!" />
        <Button Content="Hello, World!" />
        <Button Content="Hello, World!" />
        <Button Content="Hello, World!" />
        <Button Content="Hello, World!" />
    </local:MyUniformGrid>
    
    0 讨论(0)
提交回复
热议问题