WPF DesignTime Поддержка сгенерированного элемента управления - PullRequest
1 голос
/ 24 апреля 2020

Я пытаюсь создать элемент управления или стиль, который позаботится о обычной ситуации «ярлык слева, элемент управления справа». Столбец меток должен иметь одинаковую ширину для всех меток.

Моя конечная цель - создать синтаксис, подобный следующему:

<l:LayoutGroup>
    <TextBox  l:LabelHelper.Label="111" />
    <ComboBox l:LabelHelper.Label="Nice Box" ItemsSource="{Binding list}"/>
    <ComboBox />
    <Calendar l:LabelHelper.Label="Nice Calendar" HorizontalAlignment="Left"/>
    <TextBox l:LabelHelper.Label="eyyoo"/>
</l:LayoutGroup>

На самом деле это получилось двумя разными способами. Но оба не предлагают поддержку времени разработки. Кратчайшая / лучшая настройка, которую я могу придумать, что действительно предлагает поддержку времени разработки, выглядит следующим образом:

<StackPanel Orientation="Vertical" Grid.IsSharedSizeScope="True">
    <l:LayoutItem Title="cool textbox">
        <TextBox />
    </l:LayoutItem>
    <l:LayoutItem Title="short">
        <TextBox />
    </l:LayoutItem>
    <l:LayoutItem Title="ye">
        <ComboBox />
    </l:LayoutItem>
</StackPanel>

LayoutItem - это пользовательский контроль со следующим содержимым:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="auto" SharedSizeGroup="Whatever"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <TextBlock HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Path=Title}"/>
    <ContentPresenter Grid.Column="1" Content="{Binding Child"}/>
</Grid>

Так что, по сути, это просто набор сеток с ровно одним дочерним элементом и общей размерной группой.

Что я делаю, чтобы заставить мою целевую версию работать:

public static readonly DependencyProperty LabelProperty = DependencyProperty.RegisterAttached("Label",
    typeof(string), typeof(LabelHelper), new UIPropertyMetadata("", Callback));

private static void Callback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var child = d as Control;
    var parent = LogicalTreeHelper.GetParent(child);
    if (!(parent is StackPanel pnl))
        return;

    pnl.Children.Remove(child);

    var wrapper = new LayoutItem
    {
        Title = GetLabel(child),
        Child = child
    };

    pnl.Children.Add(wrapper);
}

public static string GetLabel(DependencyObject d) => (string)d.GetValue(LabelProperty);
public static void SetLabel(DependencyObject d, string value) => d.SetValue(LabelProperty, value);

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

Работает, но поддержки времени разработки нет. И я понимаю, почему дизайнеру сложно это поддерживать. Я создаю другой элемент управления "во время выполнения", но на самом деле это не время выполнения, потому что я заметил, что этот метод "обратного вызова" обновляет представление времени разработки, если оно не слишком сложное ...

Есть ли способ заставить мой желаемый синтаксис работать? Я чувствую себя очень близко, но все подходы либо добавляют текстовый блок, сетку, что-нибудь к логическому дереву, чего на самом деле нет в xaml во время разработки. Кажется, это главная проблема, и я не знаю, решаемо ли это?

Я только что понял, что поддержка Desintime почти отсутствует. Это работает, когда я добавляю новый элемент управления с помощью LabelHelper. Это только не приспосабливается, если я изменяю самый длинный лейбл. Так что Callback срабатывает во время разработки, но что-то не так.

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