UserControl 在设计器中呈现没有宽度

UserControl renders with no width in designer

我有一个包含路径元素的 UWP UserControl,路径的 Data 属性 绑定到 [=14= 的字符串 属性 ] 称为 Icon。当我将控件添加到页面并将其 Icon 属性 设置为资源项时,该控件不呈现图标并且在设计器中的宽度为 0。当我将应用程序部署到我的设备时,控件会按预期呈现。有什么办法可以解决这个问题吗?

作为参考,我正在尝试构建一个简单的工具栏,其中包含一堆可点击的图标。我确信还有其他方法可以实现这一目标,但我将其用作学习,因为我的 XAML 技能非常缺乏。我的代码可以在下面找到。

MainPage.xaml

<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Stretch">
    <local:ActionIcon  IconData="{StaticResource Test}" ></local:ActionIcon>
</StackPanel>

ActionIcon.xaml

<UserControl x:Name="userControl"
    x:Class="UwpTest.ActionIcon"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UwpTest"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="200"
    d:DesignWidth="200">
    <Viewbox Stretch="UniformToFill">
        <Path Stretch="UniformToFill" 
              Data="{Binding IconData, ElementName=userControl}" 
              Fill="Black" />
    </Viewbox>
</UserControl>

ActionIcon.xaml.cs

public sealed partial class ActionIcon : UserControl
    {
        public ActionIcon()
        {
            InitializeComponent();
        }

        public string IconData
        {
            get
            {
                return (string) GetValue(IconDataProperty);
            }
            set
            {
                SetValue(IconDataProperty, value);
            }
        }

        public static readonly DependencyProperty IconDataProperty = DependencyProperty.Register(
            "IconData", typeof(string), typeof(ActionIcon), new PropertyMetadata(default(string)));
    }

ResourceDictionary 条目

<x:String x:Key="Test">M10,16.5V7.5L16,12M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z</x:String>

简而言之,问题是 IconData 和 Path.Data 的类型不匹配。虽然 IconData 是一个字符串,但 Path.Data 需要一个 Geometry。因此,如果您想将路径的数据放入资源字典中,其类型必须是 Geometry 或其子class之一。考虑一下,当绑定失败时 WPF 不会抛出异常。相反,您会在 Visual Studio.

的 Output-Window 中收到一条消息

但是为什么直接设置Path.Data-属性就可以使用字符串呢?

路径从来没有真正得到一个字符串。当 XAML 解析器得到 属性 的错误类型时,它会查看它期望的类型 class。它正在那里搜索 TypeConversion-Attribute。解析器在看Geometry的时候,发现有这样一个属性:

[TypeConverter(typeof(GeometryConverter))]
abstract partial class Geometry

该属性指定了一个 TypeConverter。对于Geometry,它是GeomtryConverter,它可以将字符串转换为Geometry。 msdn 上有一篇关于此的文章,如果您想了解更多信息:How to: Implement a Type Converter

很好,但是我如何在 ResourceDictionaries 中使用 Geomtries?

一旦您尝试创建路径而不将字符串分配给 Path.Data,事情就会变得清晰起来。之前的简单贝塞尔曲线:

<Path Data="M 10,100 C 10,300 300,-200 300,100" />

及之后:

<Path>
        <Path.Data>
            <PathGeometry>
                <PathFigure StartPoint="10,100">
                    <BezierSegment Point1="10,300" Point2="300,-200" Point3="300,100"/>
                </PathFigure>
            </PathGeometry>
        </Path.Data>
    </Path>

TypeConverter 产生这样的输出。只有点再次由 TypeConverter 转换。然而,下一步很简单:只需将 PathGeometry 放入 ResourceDictionary。

作为一个小节点:您可以通过将用户控件 DataContext 设置为其自身来避免对每个绑定使用 ElementName:

<UserControl DataContext={Binding RelativeSource={RelativeSource Self}}" />