xaml绑定中的灾难性故障

时间:2015-10-22 20:27:22

标签: c# xaml canvas windows-10 itemscontrol

我正在开发Windows 10 Universal App。我的代码如下:

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))

分配给Canvas坐标xaml中的静态数字按预期工作。

为什么会出现错误并且代码不起作用?

1 个答案:

答案 0 :(得分:1)

我在构建通用Windows平台应用程序时自己偶然发现了这个问题。

做了一些谷歌搜索,找到this文章。

非常有帮助。我将他的SetterValueBindingHelper课程复制到我自己的项目中。之后,我进行了1次调整,因为

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事件处理程序等。