Привязка к детям. Счет - PullRequest
       2

Привязка к детям. Счет

4 голосов
/ 19 августа 2010

Я использую привязку вида

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

Несмотря на добавление дочерних элементов в xaml, когда я прерываю конвертер, значение всегда равно 0.

Я предполагаю, что потомки добавляются только после вызова этой привязки.

Я также предполагаю, что привязка прерывается после того, как она была вызвана один раз, потому что .Count является свойством только для чтения (у меня была похожая проблема раньше, когда мне приходилось добавлять пустой установщик в свойство для поддержки привязки и дурачить WPF ) следовательно, привязка не обновляется после добавления потомков.

Однако, я застрял в той части, где вы придумали решение проблемы и заставили ее работать ... = /

<UniformGrid 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!" />
   </UniformGrid>

Спасибо, Rabit

Ответы [ 2 ]

9 голосов
/ 19 августа 2010

Это потому, что UIElementCollection (тип свойства Children) не вызывает уведомлений при добавлении или удалении нового элемента, поэтому привязка не обновляется

Однако вы можете создать свой собственный UniformGrid и переопределить свойство CreateUIElementCollection, чтобы создать экземпляр пользовательской коллекции, которая наследует UIElementCollection и реализует INotifyCollectionChanged.

Вот базовая реализация:

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

1024 * 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 голосов
/ 01 января 2019
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)));
    }
}

Вместо этого используйте свойство ChildCount.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...