xaml绑定中的灾难性失败
本文关键字:灾难性 失败 绑定 xaml | 更新日期: 2023-09-27 18:18:49
我正在开发Windows 10通用应用程序。我有以下代码:
xaml:<Page
x:Class="MyProject.BlankPage1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyProject"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
>
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Purple"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding X}"/>
<Setter Property="Canvas.Top" Value="{Binding Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Fill="Red" Width="50" Height="50"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Page>
和后面的代码:
namespace MyProject
{
public sealed partial class BlankPage1 : Page
{
public BlankPage1()
{
DataContext =
new[]
{
new { X = 50.0, Y = 100.0 },
new { X = 220.0, Y = 170.0 }
};
InitializeComponent();
}
}
}
不幸的是,矩形没有显示在窗口中。我得到编译错误:
Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))
在xaml中分配Canvas坐标的静态数字工作正常。
为什么会出现错误并且代码不能工作?
我在开发通用Windows平台应用程序时偶然发现了这个问题。
我搜索了一下,找到了这篇文章。
这很有帮助。我把他的SetterValueBindingHelper
类复制到我自己的项目中。之后,我做了一个调整,因为
type = System.Type.GetType(item.Type).GetTypeInfo();
当您在XAML绑定中执行Type="Canvas"
时,给出一个异常。它首先尝试在当前程序集中找到Canvas
类。这将返回null
,然后调用.GetTypeInfo()
并抛出NullReferenceException。
实现了c# 6.0的新Null-Conditional Operator
,解决了这个问题。紧接着的代码检查type
是否为空,然后遍历所有加载的程序集以找到Canvas
。
type = System.Type.GetType(item.Type)?.GetTypeInfo();
他的第二个用法示例奇怪地与Canvas
元素相关。
另一个来自我的Project VisualDesigner的例子:
这是我最后的XAML,基于他的例子:
<ItemsControl Grid.Column="1" ItemsSource="{Binding CanvasItems}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="helpers:SetterValueBindingHelper.PropertyBinding">
<Setter.Value>
<helpers:SetterValueBindingHelper>
<helpers:SetterValueBindingHelper Type="Canvas" Property="Left" Binding="{Binding WindowX, Mode=TwoWay}" />
<helpers:SetterValueBindingHelper Type="Canvas" Property="Top" Binding="{Binding WindowY, Mode=TwoWay}" />
</helpers:SetterValueBindingHelper>
</Setter.Value>
</Setter>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<applicationwindow:ApplicationWindow Width="{Binding WindowWidth}" Height="{Binding WindowHeight}" DataContext="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
helpers:
为SetterValueBindingHelper
所在的命名空间。ApplicationWindow
在我的情况下是一个自定义UserControl。CanvasItems
是ObservableCollection<ApplicationWindowViewModel>
,这是我的ApplicationWindowViewModel
:
[ImplementPropertyChanged]
public class ApplicationWindowViewModel : ViewModelBase
{
public string Title { get; set; }
public double WindowX { get; set; } = 10;
public double WindowY { get; set; } = 10;
public int WindowWidth { get; set; } = 300;
public int WindowHeight { get; set; } = 200;
}
在这个例子中,我使用Fody。PropertyChanged来处理X/Y/Width/Height属性上的属性改变事件,如果你不使用这个包,不要忘记实现你自己的PropertyChanged事件处理程序,等等