首页 > 解决方案 > WPF DesignTime 支持生成的控件

问题描述

我正在尝试构建一个控件或样式来处理通常的“左侧标签,右侧控件”情况。所有标签的标签列应具有相同的宽度。

我的最终目标是拥有这样的语法:

<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 添加新控件时起作用。如果我更改最长的标签,它只是不会调整。所以回调在设计时触发,但有些事情不太对。

标签: c#wpfxaml

解决方案


推荐阅读