获取 DataTemplate 的子项会抛出 "catastrophic failure"(WP 8.1)
Getting children of DataTemplate throws "catastrophic failure" (WP 8.1)
我正在尝试创建一个 Windows Phone 8.1 应用程序。每当我尝试获取 DataTemplate 的子项(这是必需的,因为它们嵌入在 ListView 中)时,我都会得到一个详细说明 a
的异常
Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))
我在这里做了一个非常简单的复现:
在 Visual Studio 中,创建一个新的 Windows Phone 空白应用程序模板。在 MainPage.xaml 的 OnNavigatedTo 事件处理程序中,添加 一行代码 :
var count = VisualTreeHelper.GetChildrenCount(new DataTemplate());
当你调试这个应用程序时,它会直接说 "An unhandled System.Exception has occured in user code."
我已经检查了 MSDN 以确保此方法不会抛出任何异常。
它失败了,因为 DataTemplate
不是可视对象并且没有可视子对象。 (显然 VisualTreeHelper.GetChildrenCount
实际上并没有检查您是否正在传递视觉效果,这就是为什么您看到灾难性故障而不是正常异常的原因)。
通常您不需要查看 ListView 的可视化树。通常,您可以将 ItemsSource 设置为自定义 class 的集合,其中包含您需要的所有属性。
如果您仍然需要 ListViewItem 中的实际视觉效果 - 这是极端情况下的最后手段 - 那么您可以创建一个自定义附加 属性(-ies) 并将其附加到相关视觉效果) 在你的数据模板中。当您附加的 属性 更改事件触发时,事件发送者将是相关的视觉对象,而该发送者的 DataContext 将是该列表项的数据值。
例如,如果您在 ListView
中有一个按钮,并希望单击该按钮来触发一个动作,那么您可以这样做:
<ListView.ItemTemplate>
<DataTemplate>
<Button MyClickHelper.ClickHandler="{Binding}"/>
</DataTemplate>
</ListView.ItemTemplate>
然后,在你的 class MyClickHelper
:
private static void OnClickHandlerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var button = (Button)d;
var data = (MyDataType)e.NewValue;
button.Click += (btn, args) =>
{
// do action here based on data above
}
}
这称为附加行为 - 修改按钮行为的附加 属性。这是一个有用的模式,它在代码的不同部分之间保持良好的界限,并允许每个按钮具有规定的行为,而无需某些必须直接管理所有不同按钮的主人 class。
我正在尝试创建一个 Windows Phone 8.1 应用程序。每当我尝试获取 DataTemplate 的子项(这是必需的,因为它们嵌入在 ListView 中)时,我都会得到一个详细说明 a
的异常Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))
我在这里做了一个非常简单的复现:
在 Visual Studio 中,创建一个新的 Windows Phone 空白应用程序模板。在 MainPage.xaml 的 OnNavigatedTo 事件处理程序中,添加 一行代码 :
var count = VisualTreeHelper.GetChildrenCount(new DataTemplate());
当你调试这个应用程序时,它会直接说 "An unhandled System.Exception has occured in user code."
我已经检查了 MSDN 以确保此方法不会抛出任何异常。
它失败了,因为 DataTemplate
不是可视对象并且没有可视子对象。 (显然 VisualTreeHelper.GetChildrenCount
实际上并没有检查您是否正在传递视觉效果,这就是为什么您看到灾难性故障而不是正常异常的原因)。
通常您不需要查看 ListView 的可视化树。通常,您可以将 ItemsSource 设置为自定义 class 的集合,其中包含您需要的所有属性。
如果您仍然需要 ListViewItem 中的实际视觉效果 - 这是极端情况下的最后手段 - 那么您可以创建一个自定义附加 属性(-ies) 并将其附加到相关视觉效果) 在你的数据模板中。当您附加的 属性 更改事件触发时,事件发送者将是相关的视觉对象,而该发送者的 DataContext 将是该列表项的数据值。
例如,如果您在 ListView
中有一个按钮,并希望单击该按钮来触发一个动作,那么您可以这样做:
<ListView.ItemTemplate>
<DataTemplate>
<Button MyClickHelper.ClickHandler="{Binding}"/>
</DataTemplate>
</ListView.ItemTemplate>
然后,在你的 class MyClickHelper
:
private static void OnClickHandlerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var button = (Button)d;
var data = (MyDataType)e.NewValue;
button.Click += (btn, args) =>
{
// do action here based on data above
}
}
这称为附加行为 - 修改按钮行为的附加 属性。这是一个有用的模式,它在代码的不同部分之间保持良好的界限,并允许每个按钮具有规定的行为,而无需某些必须直接管理所有不同按钮的主人 class。