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}}" />
我有一个包含路径元素的 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}}" />