我已经成为 WPF 开发人员大约 10 年了,我从其中看到了很多各种形状和大小的白痴,但今天我偶然发现了一批新鲜的雄性牛粪,它只是绝对是蛋糕。实际上,存在的每一个蛋糕。
将转换器放在窗口资源列表的顶部会以某种方式破坏其后面的 UI 对象的资源。
这是重现此问题的应用程序的最简单示例,我可以使用最少的代码:
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="clr-namespace:WpfApp1.Converters"
xmlns:system="clr-namespace:System;assembly=mscorlib"
SizeToContent="WidthAndHeight"
WindowStartupLocation="CenterScreen">
<Window.Resources>
<converters:BaseConverter x:Key="test"/>
<Grid x:Key="TestItemTemplateGrid" x:Shared="false">
<Button Content="{Binding StringFormat='Button {0}'}" Width="300"/>
</Grid>
</Window.Resources>
<ItemsControl>
<system:Int32>0</system:Int32>
<system:Int32>1</system:Int32>
<system:Int32>2</system:Int32>
<system:Int32>3</system:Int32>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl Content="{StaticResource TestItemTemplateGrid}" Margin="0,5,0,0"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Window>
转换器:
using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Markup;
namespace WpfApp1.Converters
{
public class BaseConverter : MarkupExtension, IValueConverter
{
public virtual object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return Binding.DoNothing;
}
public virtual object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return Binding.DoNothing;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
}
}
这只是在 ItemsControl 中加载可变数量的项目的简单尝试,其中每个项目都是一个 ContentControl,它将自身填充为资源中定义的 Grid。
这就是基于此 xaml 的应用程序应该的样子:
但它实际上是这样的:
就像 x:Shared 正在打破并成为现实或其他什么,只是因为转换器资源出现在它之前。
我测试过的东西:
当然,删除
<converters:BaseConverter x:Key="test"/>
可以修复它,但真正的问题是:将其放在资源列表的最后也可以修复它。
...哇。只是,哇。这是什么?我死了吗?我在做梦吗?愚人节是否被编程到 WPF 中,但它被窃听了(就像其他所有事情一样)并且晚了一个月?有人可以解释一下吗?我在这里失去了理智。
项目文件,以防万一:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
</PropertyGroup>
</Project>
按钮从ContentControl(CC)下降;使用 CC 作为按钮“内容”是多余的。这按预期工作:
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding StringFormat='Button {0}'}"
Width="300" />
</DataTemplate>
</ItemsControl.ItemTemplate>