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坐标的静态数字工作正常。

为什么会出现错误并且代码不能工作?

xaml绑定中的灾难性失败

我在开发通用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。CanvasItemsObservableCollection<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事件处理程序,等等