Silverlight:将 UIElement 绑定到 ListBoxItems 时发生 TargetInvocationException
Silverlight: TargetInvocationException Occurred by Bind UIElement To ListBoxItems
我创建了一个 ListBox
并将 ItemsSource
绑定到对象列表:
MainPage.xaml:
<Grid x:Name="LayoutRoot" Background="White"
DataContext="{StaticResource ResourceKey=ViewModel}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="47*"/>
<ColumnDefinition Width="28*"/>
</Grid.ColumnDefinitions>
<ListBox ItemsSource="{Binding Models}"
Height="200" Width="150" Grid.Column="0">
<ListBox.ItemTemplate>
<DataTemplate >
<StackPanel>
<TextBlock Text="{Binding ID ,Mode=TwoWay
,UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text="{Binding Name ,Mode=TwoWay
,UpdateSourceTrigger=PropertyChanged}"/>
<Border Child="{Binding Shape ,Mode=TwoWay
,UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Content="Change Source" Height="35" Width="100"
Grid.Column="1">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding ChangeSource}"
CommandParameter="{Binding ElementName=LayoutRoot}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
Model.cs:
public class Model
{
private string _ID;
private UIElement _Shape;
private string _Name;
public string Name
{
get { return _Name; }
set { _Name = value; }
}
public UIElement Shape
{
get { return _Shape; }
set { _Shape = value;}
}
public string ID
{
get { return _ID; }
set { _ID = value; }
}
}
和
ViewModel.cs:
public class ViewModel : INotifyPropertyChanged
{
Random rnd = new Random();
List<Color> MyColors = new List<Color>() { Colors.Gray,
Colors.Blue, Colors.Red,
Colors.Green, Colors.Yellow,
Colors.Orange, Colors.DarkGray };
private List<Model> _Models;
public List<Model> Models
{
get
{
if (_Models == null)
_Models = new List<Model>();
return _Models;
}
set { _Models = value; OnPropertyChanged("Models"); }
}
public DelegateCommand<object> ChangeSource { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string PropertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
}
public ViewModel()
{
ChangeSource = new DelegateCommand<object>(ChangeSourceCommand);
ChangeSourceItems();
}
private void ChangeSourceCommand(object obj)
{
ChangeSourceItems();
}
private void ChangeSourceItems()
{
List<Model> tmpModels = new List<Model>();
tmpModels.Add(new Model() { ID = "1", Name = "A", Shape = new Border() { Background = new SolidColorBrush(MyColors[rnd.Next(0, MyColors.Count - 1)]), Width = 10, Height = 10 } });
tmpModels.Add(new Model() { ID = "2", Name = "B", Shape = new Border() { Background = new SolidColorBrush(MyColors[rnd.Next(0, MyColors.Count - 1)]), Width = 10, Height = 10 } });
tmpModels.Add(new Model() { ID = "3", Name = "C", Shape = new Border() { Background = new SolidColorBrush(MyColors[rnd.Next(0, MyColors.Count - 1)]), Width = 10, Height = 10 } });
tmpModels.Add(new Model() { ID = "4", Name = "D", Shape = new Border() { Background = new SolidColorBrush(MyColors[rnd.Next(0, MyColors.Count - 1)]), Width = 10, Height = 10 } });
tmpModels.Add(new Model() { ID = "5", Name = "E", Shape = new Border() { Background = new SolidColorBrush(MyColors[rnd.Next(0, MyColors.Count - 1)]), Width = 10, Height = 10 } });
tmpModels.Add(new Model() { ID = "6", Name = "F", Shape = new Border() { Background = new SolidColorBrush(MyColors[rnd.Next(0, MyColors.Count - 1)]), Width = 10, Height = 10 } });
Models = tmpModels;
}
}
点击 Button
更改了模型来源。
问题:
TargetInvocationException
在单击 Button
并滚动 ListView
后发生。 为什么?
异常消息:
调用的目标抛出了异常。
InnerException 消息:
值不在预期范围内。
因为您在模型中使用 UIElement
,形状创建了不止一次并且发生了滚动 TargetInvocationException
。
您必须继承 ListBox
并覆盖 IsItemItsOwnContainerOverride
方法。
protected override bool IsItemItsOwnContainerOverride(object item)
{
Model model = (Model)item;
FrameworkElement elem = (FrameworkElement)model.Shape;
return elem.Parent != null;
}
我创建了一个 ListBox
并将 ItemsSource
绑定到对象列表:
MainPage.xaml:
<Grid x:Name="LayoutRoot" Background="White"
DataContext="{StaticResource ResourceKey=ViewModel}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="47*"/>
<ColumnDefinition Width="28*"/>
</Grid.ColumnDefinitions>
<ListBox ItemsSource="{Binding Models}"
Height="200" Width="150" Grid.Column="0">
<ListBox.ItemTemplate>
<DataTemplate >
<StackPanel>
<TextBlock Text="{Binding ID ,Mode=TwoWay
,UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text="{Binding Name ,Mode=TwoWay
,UpdateSourceTrigger=PropertyChanged}"/>
<Border Child="{Binding Shape ,Mode=TwoWay
,UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Content="Change Source" Height="35" Width="100"
Grid.Column="1">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding ChangeSource}"
CommandParameter="{Binding ElementName=LayoutRoot}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
Model.cs:
public class Model
{
private string _ID;
private UIElement _Shape;
private string _Name;
public string Name
{
get { return _Name; }
set { _Name = value; }
}
public UIElement Shape
{
get { return _Shape; }
set { _Shape = value;}
}
public string ID
{
get { return _ID; }
set { _ID = value; }
}
}
和
ViewModel.cs:
public class ViewModel : INotifyPropertyChanged
{
Random rnd = new Random();
List<Color> MyColors = new List<Color>() { Colors.Gray,
Colors.Blue, Colors.Red,
Colors.Green, Colors.Yellow,
Colors.Orange, Colors.DarkGray };
private List<Model> _Models;
public List<Model> Models
{
get
{
if (_Models == null)
_Models = new List<Model>();
return _Models;
}
set { _Models = value; OnPropertyChanged("Models"); }
}
public DelegateCommand<object> ChangeSource { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string PropertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
}
public ViewModel()
{
ChangeSource = new DelegateCommand<object>(ChangeSourceCommand);
ChangeSourceItems();
}
private void ChangeSourceCommand(object obj)
{
ChangeSourceItems();
}
private void ChangeSourceItems()
{
List<Model> tmpModels = new List<Model>();
tmpModels.Add(new Model() { ID = "1", Name = "A", Shape = new Border() { Background = new SolidColorBrush(MyColors[rnd.Next(0, MyColors.Count - 1)]), Width = 10, Height = 10 } });
tmpModels.Add(new Model() { ID = "2", Name = "B", Shape = new Border() { Background = new SolidColorBrush(MyColors[rnd.Next(0, MyColors.Count - 1)]), Width = 10, Height = 10 } });
tmpModels.Add(new Model() { ID = "3", Name = "C", Shape = new Border() { Background = new SolidColorBrush(MyColors[rnd.Next(0, MyColors.Count - 1)]), Width = 10, Height = 10 } });
tmpModels.Add(new Model() { ID = "4", Name = "D", Shape = new Border() { Background = new SolidColorBrush(MyColors[rnd.Next(0, MyColors.Count - 1)]), Width = 10, Height = 10 } });
tmpModels.Add(new Model() { ID = "5", Name = "E", Shape = new Border() { Background = new SolidColorBrush(MyColors[rnd.Next(0, MyColors.Count - 1)]), Width = 10, Height = 10 } });
tmpModels.Add(new Model() { ID = "6", Name = "F", Shape = new Border() { Background = new SolidColorBrush(MyColors[rnd.Next(0, MyColors.Count - 1)]), Width = 10, Height = 10 } });
Models = tmpModels;
}
}
点击 Button
更改了模型来源。
问题:
TargetInvocationException
在单击 Button
并滚动 ListView
后发生。 为什么?
异常消息:
调用的目标抛出了异常。
InnerException 消息:
值不在预期范围内。
因为您在模型中使用 UIElement
,形状创建了不止一次并且发生了滚动 TargetInvocationException
。
您必须继承 ListBox
并覆盖 IsItemItsOwnContainerOverride
方法。
protected override bool IsItemItsOwnContainerOverride(object item)
{
Model model = (Model)item;
FrameworkElement elem = (FrameworkElement)model.Shape;
return elem.Parent != null;
}