NotifyCollectionChangedEvent 处理程序中未处理的异常“参数不正确”
Unhandled exception `The parameter is incorrect` in NotifyCollectionChangedEvent handler
我有一个非常简单的 ListView
,它的 ItemsSource
是一个 ObservableCollection
。最好用代码展示一下:
MainPage.xaml:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Windows.UI.Xaml.Shapes"
x:Class="Test.MainPage" Background="Black" >
<Grid x:Name="Board" Background="Transparent" >
<ListView ItemsSource="{x:Bind LineList}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Line">
<StackPanel Orientation="Horizontal" Spacing="5">
<TextBlock Foreground="White" Text="{x:Bind Name}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
Mainpage.xaml.cs:
public sealed partial class MainPage : Page
{
public ObservableCollection<Line> LineList = new ObservableCollection<Line>();
public MainPage()
{
InitializeComponent();
LineList.CollectionChanged += List_CollectionChanged;
LineList.Add(new Line { Name = "Line1" });
LineList.Add(new Line { Name = "Line2" });
}
private void List_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if(e.Action == NotifyCollectionChangedAction.Add)
{
Board.Children.Add(e.NewItems[0] as Line);//if I comment out this line, no exception
}
}
}
我真正想要的是,当我在 ListView
上添加一个 Line
以显示它是 Name
时,它也会作为实际的 [=18] 添加到网格中=]. 请注意,我使用 ListView 只是为了显示这些线的名称,而在网格中我想要一个实际的 Line
形状
我不知道我做错了什么,但上面的尝试给出了规定的异常。
如果这些信息有帮助:
- 如果我不在
Grid
中添加 Line
,则不会出现异常
- 没有例外如果:
Board.Children.Add(new Line { Name = "Line2" });
我不确定这是否是您想要的,但就是这样
MainPage.xaml
<Page x:Class="App4.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App4"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<Style x:Key="LineViewItemContainerStyle"
TargetType="ListViewItem">
<Setter Property="FontFamily"
Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize"
Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="Background"
Value="{ThemeResource ListViewItemBackground}" />
<Setter Property="Foreground"
Value="{ThemeResource ListViewItemForeground}" />
<Setter Property="TabNavigation"
Value="Local" />
<Setter Property="IsHoldingEnabled"
Value="True" />
<Setter Property="Padding"
Value="0" />
<Setter Property="HorizontalContentAlignment"
Value="Stretch" />
<Setter Property="VerticalContentAlignment"
Value="Stretch" />
<Setter Property="MinWidth"
Value="{ThemeResource ListViewItemMinWidth}" />
<Setter Property="MinHeight"
Value="{ThemeResource ListViewItemMinHeight}" />
<Setter Property="AllowDrop"
Value="False" />
<Setter Property="UseSystemFocusVisuals"
Value="True" />
<Setter Property="FocusVisualMargin"
Value="0" />
<Setter Property="FocusVisualPrimaryBrush"
Value="{ThemeResource ListViewItemFocusVisualPrimaryBrush}" />
<Setter Property="FocusVisualPrimaryThickness"
Value="2" />
<Setter Property="FocusVisualSecondaryBrush"
Value="{ThemeResource ListViewItemFocusVisualSecondaryBrush}" />
<Setter Property="FocusVisualSecondaryThickness"
Value="1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<ListViewItemPresenter x:Name="Root"
CheckBrush="{ThemeResource ListViewItemCheckBrush}"
ContentMargin="{TemplateBinding Padding}"
CheckBoxBrush="{ThemeResource ListViewItemCheckBoxBrush}"
ContentTransitions="{TemplateBinding ContentTransitions}"
CheckMode="{ThemeResource ListViewItemCheckMode}"
DragOpacity="{ThemeResource ListViewItemDragThemeOpacity}"
DisabledOpacity="{ThemeResource ListViewItemDisabledThemeOpacity}"
DragBackground="{ThemeResource ListViewItemDragBackground}"
DragForeground="{ThemeResource ListViewItemDragForeground}"
FocusVisualSecondaryBrush="{TemplateBinding FocusVisualSecondaryBrush}"
FocusVisualPrimaryThickness="{TemplateBinding FocusVisualPrimaryThickness}"
FocusVisualSecondaryThickness="{TemplateBinding FocusVisualSecondaryThickness}"
FocusBorderBrush="{ThemeResource ListViewItemFocusBorderBrush}"
FocusVisualMargin="{TemplateBinding FocusVisualMargin}"
FocusVisualPrimaryBrush="{TemplateBinding FocusVisualPrimaryBrush}"
FocusSecondaryBorderBrush="{ThemeResource ListViewItemFocusSecondaryBorderBrush}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
Control.IsTemplateFocusTarget="True"
PressedBackground="{ThemeResource ListViewItemBackgroundPressed}"
PlaceholderBackground="{ThemeResource ListViewItemPlaceholderBackground}"
PointerOverForeground="{ThemeResource ListViewItemForegroundPointerOver}"
PointerOverBackground="{ThemeResource ListViewItemBackgroundPointerOver}"
ReorderHintOffset="{ThemeResource ListViewItemReorderHintThemeOffset}"
SelectedForeground="{ThemeResource ListViewItemForegroundSelected}"
SelectionCheckMarkVisualEnabled="{ThemeResource ListViewItemSelectionCheckMarkVisualEnabled}"
SelectedBackground="{ThemeResource ListViewItemBackgroundSelected}"
SelectedPressedBackground="{ThemeResource ListViewItemBackgroundSelectedPressed}"
SelectedPointerOverBackground="{ThemeResource ListViewItemBackgroundSelectedPointerOver}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Selected" />
<VisualState x:Name="PointerOver">
<VisualState.Setters>
<Setter Target="Root.(RevealBrush.State)"
Value="PointerOver" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="PointerOverSelected">
<VisualState.Setters>
<Setter Target="Root.(RevealBrush.State)"
Value="PointerOver" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="PointerOverPressed">
<VisualState.Setters>
<Setter Target="Root.(RevealBrush.State)"
Value="Pressed" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Pressed">
<VisualState.Setters>
<Setter Target="Root.(RevealBrush.State)"
Value="Pressed" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="PressedSelected">
<VisualState.Setters>
<Setter Target="Root.(RevealBrush.State)"
Value="Pressed" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="DisabledStates">
<VisualState x:Name="Enabled" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Target="Root.RevealBorderThickness"
Value="0" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</ListViewItemPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<Grid Background="Transparent">
<ListView ItemContainerStyle="{StaticResource LineViewItemContainerStyle}"
ItemsSource="{x:Bind Lines, Mode=OneTime}"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:LineViewModel">
<Grid x:Name="ItemGrid">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Foreground="Black"
Text="{x:Bind Name, Mode=OneWay}" />
<Border Grid.Row="1"
BorderBrush="Black"
BorderThickness="1" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Page>
MainPage.xaml.cs
public sealed partial class MainPage : Page
{
public ObservableCollection<LineViewModel> Lines = new ObservableCollection<LineViewModel>();
public MainPage()
{
InitializeComponent();
Lines.Add(new LineViewModel { Name = "Line1" });
Lines.Add(new LineViewModel { Name = "Line2" });
}
}
public class LineViewModel
{
public string Name { get; set; }
}
请注意,我没有使用 Line
,而是使用了 Border
。此外,我需要重写基数 ListViewItemContainerStyle
以将 HorizontalContentAlignment
和 VerticalContentAlignment
设置为 Stretch
,以便 DataTemplate
元素可以占据整个 space ] 项
结果:
我一直在摆弄你的代码,我能够找到你的代码有什么问题。但是我不太确定为什么会这样。
您收到错误的原因是您尝试使用与您的 ListView.ItemsSource
绑定的 UIElement
(即 Line
)的相同实例.为什么它失败了,对我来说有点神秘。我怀疑禁止 Bind
并将相同的 UIElement
添加到 XAML,因为它可能会创建绑定循环!?不过,这只是一个大胆的猜测。无论如何...
你不应该使用 UIElement
作为绑定上下文——我想不出你会做这样的事情的任何场景。根据我之前的回答(例如 LineViewModel
)创建一个单独的模型,并将其用作您的 BindingContext
,您会过得更好。您的 MainPage.xaml.cs 代码可能如下所示:
public sealed partial class MainPage : Page
{
public ObservableCollection<LineViewModel> Lines = new ObservableCollection<LineViewModel>();
public MainPage()
{
InitializeComponent();
Lines.CollectionChanged += LinesOnCollectionChanged;
Lines.Add(new LineViewModel { Name = "Line1" });
Lines.Add(new LineViewModel { Name = "Line2" });
}
private void LinesOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
MainGrid.Children.Add(new Line()
{
Name = (e.NewItems[0] as LineViewModel)?.Name ?? string.Empty,
Stroke = new SolidColorBrush(Colors.Black),
StrokeThickness = 12,
X1 = 0,
X2 = 10000
});
}
}
}
public class LineViewModel
{
public string Name { get; set; }
}
根据我之前的回答MainPage.xaml将保持不变
我有一个非常简单的 ListView
,它的 ItemsSource
是一个 ObservableCollection
。最好用代码展示一下:
MainPage.xaml:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Windows.UI.Xaml.Shapes"
x:Class="Test.MainPage" Background="Black" >
<Grid x:Name="Board" Background="Transparent" >
<ListView ItemsSource="{x:Bind LineList}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Line">
<StackPanel Orientation="Horizontal" Spacing="5">
<TextBlock Foreground="White" Text="{x:Bind Name}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
Mainpage.xaml.cs:
public sealed partial class MainPage : Page
{
public ObservableCollection<Line> LineList = new ObservableCollection<Line>();
public MainPage()
{
InitializeComponent();
LineList.CollectionChanged += List_CollectionChanged;
LineList.Add(new Line { Name = "Line1" });
LineList.Add(new Line { Name = "Line2" });
}
private void List_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if(e.Action == NotifyCollectionChangedAction.Add)
{
Board.Children.Add(e.NewItems[0] as Line);//if I comment out this line, no exception
}
}
}
我真正想要的是,当我在 ListView
上添加一个 Line
以显示它是 Name
时,它也会作为实际的 [=18] 添加到网格中=]. 请注意,我使用 ListView 只是为了显示这些线的名称,而在网格中我想要一个实际的 Line
形状
我不知道我做错了什么,但上面的尝试给出了规定的异常。
如果这些信息有帮助:
- 如果我不在
Grid
中添加 - 没有例外如果:
Board.Children.Add(new Line { Name = "Line2" });
Line
,则不会出现异常
我不确定这是否是您想要的,但就是这样
MainPage.xaml
<Page x:Class="App4.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App4"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<Style x:Key="LineViewItemContainerStyle"
TargetType="ListViewItem">
<Setter Property="FontFamily"
Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize"
Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="Background"
Value="{ThemeResource ListViewItemBackground}" />
<Setter Property="Foreground"
Value="{ThemeResource ListViewItemForeground}" />
<Setter Property="TabNavigation"
Value="Local" />
<Setter Property="IsHoldingEnabled"
Value="True" />
<Setter Property="Padding"
Value="0" />
<Setter Property="HorizontalContentAlignment"
Value="Stretch" />
<Setter Property="VerticalContentAlignment"
Value="Stretch" />
<Setter Property="MinWidth"
Value="{ThemeResource ListViewItemMinWidth}" />
<Setter Property="MinHeight"
Value="{ThemeResource ListViewItemMinHeight}" />
<Setter Property="AllowDrop"
Value="False" />
<Setter Property="UseSystemFocusVisuals"
Value="True" />
<Setter Property="FocusVisualMargin"
Value="0" />
<Setter Property="FocusVisualPrimaryBrush"
Value="{ThemeResource ListViewItemFocusVisualPrimaryBrush}" />
<Setter Property="FocusVisualPrimaryThickness"
Value="2" />
<Setter Property="FocusVisualSecondaryBrush"
Value="{ThemeResource ListViewItemFocusVisualSecondaryBrush}" />
<Setter Property="FocusVisualSecondaryThickness"
Value="1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<ListViewItemPresenter x:Name="Root"
CheckBrush="{ThemeResource ListViewItemCheckBrush}"
ContentMargin="{TemplateBinding Padding}"
CheckBoxBrush="{ThemeResource ListViewItemCheckBoxBrush}"
ContentTransitions="{TemplateBinding ContentTransitions}"
CheckMode="{ThemeResource ListViewItemCheckMode}"
DragOpacity="{ThemeResource ListViewItemDragThemeOpacity}"
DisabledOpacity="{ThemeResource ListViewItemDisabledThemeOpacity}"
DragBackground="{ThemeResource ListViewItemDragBackground}"
DragForeground="{ThemeResource ListViewItemDragForeground}"
FocusVisualSecondaryBrush="{TemplateBinding FocusVisualSecondaryBrush}"
FocusVisualPrimaryThickness="{TemplateBinding FocusVisualPrimaryThickness}"
FocusVisualSecondaryThickness="{TemplateBinding FocusVisualSecondaryThickness}"
FocusBorderBrush="{ThemeResource ListViewItemFocusBorderBrush}"
FocusVisualMargin="{TemplateBinding FocusVisualMargin}"
FocusVisualPrimaryBrush="{TemplateBinding FocusVisualPrimaryBrush}"
FocusSecondaryBorderBrush="{ThemeResource ListViewItemFocusSecondaryBorderBrush}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
Control.IsTemplateFocusTarget="True"
PressedBackground="{ThemeResource ListViewItemBackgroundPressed}"
PlaceholderBackground="{ThemeResource ListViewItemPlaceholderBackground}"
PointerOverForeground="{ThemeResource ListViewItemForegroundPointerOver}"
PointerOverBackground="{ThemeResource ListViewItemBackgroundPointerOver}"
ReorderHintOffset="{ThemeResource ListViewItemReorderHintThemeOffset}"
SelectedForeground="{ThemeResource ListViewItemForegroundSelected}"
SelectionCheckMarkVisualEnabled="{ThemeResource ListViewItemSelectionCheckMarkVisualEnabled}"
SelectedBackground="{ThemeResource ListViewItemBackgroundSelected}"
SelectedPressedBackground="{ThemeResource ListViewItemBackgroundSelectedPressed}"
SelectedPointerOverBackground="{ThemeResource ListViewItemBackgroundSelectedPointerOver}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Selected" />
<VisualState x:Name="PointerOver">
<VisualState.Setters>
<Setter Target="Root.(RevealBrush.State)"
Value="PointerOver" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="PointerOverSelected">
<VisualState.Setters>
<Setter Target="Root.(RevealBrush.State)"
Value="PointerOver" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="PointerOverPressed">
<VisualState.Setters>
<Setter Target="Root.(RevealBrush.State)"
Value="Pressed" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Pressed">
<VisualState.Setters>
<Setter Target="Root.(RevealBrush.State)"
Value="Pressed" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="PressedSelected">
<VisualState.Setters>
<Setter Target="Root.(RevealBrush.State)"
Value="Pressed" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="DisabledStates">
<VisualState x:Name="Enabled" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Target="Root.RevealBorderThickness"
Value="0" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</ListViewItemPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<Grid Background="Transparent">
<ListView ItemContainerStyle="{StaticResource LineViewItemContainerStyle}"
ItemsSource="{x:Bind Lines, Mode=OneTime}"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:LineViewModel">
<Grid x:Name="ItemGrid">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Foreground="Black"
Text="{x:Bind Name, Mode=OneWay}" />
<Border Grid.Row="1"
BorderBrush="Black"
BorderThickness="1" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Page>
MainPage.xaml.cs
public sealed partial class MainPage : Page
{
public ObservableCollection<LineViewModel> Lines = new ObservableCollection<LineViewModel>();
public MainPage()
{
InitializeComponent();
Lines.Add(new LineViewModel { Name = "Line1" });
Lines.Add(new LineViewModel { Name = "Line2" });
}
}
public class LineViewModel
{
public string Name { get; set; }
}
请注意,我没有使用 Line
,而是使用了 Border
。此外,我需要重写基数 ListViewItemContainerStyle
以将 HorizontalContentAlignment
和 VerticalContentAlignment
设置为 Stretch
,以便 DataTemplate
元素可以占据整个 space ] 项
结果:
我一直在摆弄你的代码,我能够找到你的代码有什么问题。但是我不太确定为什么会这样。
您收到错误的原因是您尝试使用与您的 ListView.ItemsSource
绑定的 UIElement
(即 Line
)的相同实例.为什么它失败了,对我来说有点神秘。我怀疑禁止 Bind
并将相同的 UIElement
添加到 XAML,因为它可能会创建绑定循环!?不过,这只是一个大胆的猜测。无论如何...
你不应该使用 UIElement
作为绑定上下文——我想不出你会做这样的事情的任何场景。根据我之前的回答(例如 LineViewModel
)创建一个单独的模型,并将其用作您的 BindingContext
,您会过得更好。您的 MainPage.xaml.cs 代码可能如下所示:
public sealed partial class MainPage : Page
{
public ObservableCollection<LineViewModel> Lines = new ObservableCollection<LineViewModel>();
public MainPage()
{
InitializeComponent();
Lines.CollectionChanged += LinesOnCollectionChanged;
Lines.Add(new LineViewModel { Name = "Line1" });
Lines.Add(new LineViewModel { Name = "Line2" });
}
private void LinesOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
MainGrid.Children.Add(new Line()
{
Name = (e.NewItems[0] as LineViewModel)?.Name ?? string.Empty,
Stroke = new SolidColorBrush(Colors.Black),
StrokeThickness = 12,
X1 = 0,
X2 = 10000
});
}
}
}
public class LineViewModel
{
public string Name { get; set; }
}
根据我之前的回答MainPage.xaml将保持不变