Пользовательская сетка WPF детей не refre sh в представлении дизайна - PullRequest
0 голосов
/ 22 января 2020

Моя конечная цель - упростить написание сетки, особенно написание Grid.Row="x" и Grid.Column="y". Для этого я создаю новый класс, наследуемый от Grid, и переопределяю метод theOnInitialized. Это работает нормально, но только во время выполнения, а не в представлении конструктора (представление в Visual Studio для редактирования XAML)

Я пытаюсь переопределить метод OnVisualChildrenChanged, но этот метод вызывается перед инициализацией элемента, поэтому я не могу получить всю информацию о товаре, которую я хочу. Я пытаюсь записать событие item.Initialized, но оно никогда не вызывается в режиме конструктора.

Единственный способ, который я нашел, но не нашел решения, - добавить бесполезный элемент в конец коллекции и вызвать функцию ChildUpdate в OnVisualChildrenChanged. При таком решении только последний элемент не инициализируется, но не используется. Моя цель - уменьшить размер кода, и ошибка возникает только для представления проекта.

пример для воспроизведения:

    <local:CustomGrid x:Name="myGrid" Margin="5">
        <TextBlock x:Name="TextBlock1"/>
        <TextBox x:Name="TextBox1"/>
    </local:CustomGrid>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace AtlantisUpdater
{
    class CustomGrid : Grid
    {
        protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved)
        {
            if (visualAdded != null)
                ((FrameworkElement)visualAdded).Initialized += CustomGrid_Initialized;

            if (visualRemoved != null)
                ((FrameworkElement)visualRemoved).Initialized -= CustomGrid_Initialized;

            //UpdateChildren();
            base.OnVisualChildrenChanged(visualAdded, visualRemoved);
        }

        private void CustomGrid_Initialized(object sender, EventArgs e)
        {
            if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
                throw new Exception("My error");
            UpdateChildren();
        }

        protected override void OnInitialized(EventArgs e)
        {
            UpdateChildren();
            base.OnInitialized(e);
        }

        protected void UpdateChildren()
        {
            int rowNb = RowDefinitions.Count;
            int columnNb = ColumnDefinitions.Count;
            if (columnNb == 0)
            {
                ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Auto) });
                ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
                columnNb = ColumnDefinitions.Count;
            }
            int nextRow = 0;
            int nextColumn = 0;
            foreach (UIElement child in Children)
            {
                //happens while editing the children collection in xaml
                //if we don't handle this, the Designer throws an exception
                if (child == null)
                    continue;

                string name = ((FrameworkElement)child).Name; // empty for the last child, when call from OnVisualChildrenChanged 
                if (nextRow >= RowDefinitions.Count)
                    RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });

                bool rowIsDefined = child.ReadLocalValue(RowProperty) != DependencyProperty.UnsetValue;
                bool columnIsDefined = child.ReadLocalValue(ColumnProperty) != DependencyProperty.UnsetValue;
                if (rowIsDefined)
                {
                    for (int i = RowDefinitions.Count; i < GetRow(child) + 1; i++)
                        RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });
                }
                if (!rowIsDefined && !columnIsDefined)
                {
                    SetRow(child, nextRow);
                    SetColumn(child, nextColumn);

                    nextColumn += GetColumnSpan(child);

                    if (nextColumn >= columnNb)
                    {
                        nextColumn = 0;
                        nextRow++;
                    }
                }

1 Ответ

0 голосов
/ 22 января 2020

Проблема, похоже, в вашем UpdateChildren методе. Этот метод имеет nextRow, nextColumn в качестве локальных переменных и всегда имеет значение 0, и этот метод вызывается каждый раз, когда инициализируется визуальный дочерний элемент. Таким образом, все дети получают свои значения Row и Column как 0.

Вы должны сделать nextRow и nextColumn как поля уровня класса, тогда это будет работать, как и ожидалось.

class CustomGrid : Grid
{
    private int _nextRow = 0;
    private int _nextColumn = 0;

    protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved)
    {
        base.OnVisualChildrenChanged(visualAdded, visualRemoved);
        UpdateChildren();
    }

    void UpdateChildren()
    {
        int rowNb = RowDefinitions.Count;
        int columnNb = ColumnDefinitions.Count;
        if (columnNb == 0)
        {
            ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(50, GridUnitType.Star) });
            ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(50, GridUnitType.Star) });
            columnNb = ColumnDefinitions.Count;
        }
        foreach (UIElement child in Children)
        {
            //happens while editing the children collection in xaml
            //if we don't handle this, the Designer throws an exception
            if (child == null)
                continue;

            string name = ((FrameworkElement)child).Name; // empty for the last child, when call from OnVisualChildrenChanged 
            if (_nextRow >= RowDefinitions.Count)
                RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });

            bool rowIsDefined = child.ReadLocalValue(RowProperty) != DependencyProperty.UnsetValue;
            bool columnIsDefined = child.ReadLocalValue(ColumnProperty) != DependencyProperty.UnsetValue;
            if (rowIsDefined)
            {
                for (int i = RowDefinitions.Count; i < GetRow(child) + 1; i++)
                    RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });
            }
            if (!rowIsDefined && !columnIsDefined)
            {
                SetRow(child, _nextRow);
                SetColumn(child, _nextColumn);

                _nextColumn += GetColumnSpan(child);

                if (_nextColumn >= columnNb)
                {
                    _nextColumn = 0;
                    _nextRow++;
                }
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...