Моя конечная цель - упростить написание сетки, особенно написание 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++;
}
}