【发布时间】:2011-08-12 20:05:13
【问题描述】:
在我的应用程序中,模板化表单需要在堆栈面板中显示用户控件列表。我想我可以在表单上使用 ItemsControl 并将其绑定到公开“子用户控件”的集合。这种方法在第一次加载模板表单时效果很好,但如果我对子用户控件的 Observable 集合进行任何更改,我会收到异常“值不在预期范围内”。
我浏览了很多帖子,但似乎没有一个解决方案有效。我正在粘贴一个示例代码,显示我正在谈论的问题。示例代码有
包含 ItemsCONtrol 的主页。 Itemscontrol 绑定到一个 AnyControl 类型的 Observablecollection。
类 AnyControl 具有公共属性 AttachedControl。这 AttachedControl 是类型对象。
加载主页时,我创建了 2 个 AnyControl 实例并将 AttachedControl 属性设置为文本框实例。
主页有 3 个按钮
- 显示全部。它设置了主页的数据上下文和两个 文本框显示在表单上。
- 删除第二个控件。点击这个 按钮从 ObservableCollection 和 第二个文本框消失。
- 恢复第二个控制。点击这个 按钮将第二个条目添加回 Observable Collection。 从逻辑上讲,第二个文本框应该显示在表单上,而是 我得到了例外。
代码从这里开始..... MainPage.xaml.cs
public partial class MainPage : UserControl, INotifyPropertyChanged
{
public AnyControl control1;
public AnyControl control2;
public MainPage()
{
InitializeComponent();
control1 = new AnyControl(new TextBox() { Text = "First Textbox" });
control2 = new AnyControl(new TextBox() { Text = "Second Textbox" });
_allVMs = new ObservableCollection<AnyControl>();
_allVMs.Add(control1);
_allVMs.Add(control2);
}
private ObservableCollection<AnyControl> _allVMs;
public ObservableCollection<AnyControl> ActiveViews
{
get { return _allVMs;}
set
{
_allVMs = value;
NotifyPropertyChanged("ActiveViews");
}
}
private void Button1_Click(object sender, RoutedEventArgs e)
{
this.LayoutRoot.DataContext = this; // RecordTemplate;
}
private void Button2_Click(object sender, RoutedEventArgs e)
{
this.ActiveViews.RemoveAt(1);
NotifyPropertyChanged("ActiveViews");
}
private void Button3_Click(object sender, RoutedEventArgs e)
{
this.ActiveViews.Add(control2);
NotifyPropertyChanged("ActiveViews");
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
AnyControl.cs
public class AnyControl
{
public object AttachedControl { get; set; }
public AnyControl(object control)
{
AttachedControl = control;
}
}
MainPage.xaml
<UserControl x:Class="SilverlightApplication2.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:layoutToolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Layout.Toolkit"
xmlns:layoutPrimitivesToolkit="clr-namespace:System.Windows.Controls.Primitives;assembly=System.Windows.Controls.Layout.Toolkit"
xmlns:local="clr-namespace:SilverlightApplication2"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<ItemsControl ItemsSource="{Binding ActiveViews}" x:Name="ItemsControl">
<ItemsControl.ItemsPanel >
<ItemsPanelTemplate x:Name="a7777">
<VirtualizingStackPanel Orientation="Vertical" x:Name="222"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding AttachedControl}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Orientation="Horizontal" Grid.Row="1">
<Button Content="Show All" Height="22" Click="Button1_Click" Margin="5,0,5,0" />
<Button Content="Remove second control" Height="22" Click="Button2_Click" Margin="5,0,5,0"/>
<Button Content="Restore second control" Height="22" Click="Button3_Click" Margin="5,0,5,0"/>
</StackPanel>
</Grid>
非常感谢任何帮助。 谢谢 一个
【问题讨论】:
-
请提供异常详情
-
它抛出“值不在预期范围内。”例外。
-
您正在做的事情很奇怪,试图将 UIElements 的实例视为您正在做的数据,而理论上可能会给您带来痛苦。你为什么做这个?在我看来,更好的方法是将实际数据绑定到
Content和DataTemplate到ContentTemplate。 -
您好 AnthonyWJones,我正在使用 MVVM 模式的 ViewModelFirst 方法,其中 ViewModel 决定显示哪个视图。这不是一种非常常见的方法,但当您的视图是 ChildWindows 时非常有用。
-
“值不在预期范围内”通常表明您的代码导致 UIElement 多次放置在可视化树中,因此它有多个父级,这是无效的。我建议遵循@AnthonyWJones 的建议
标签: .net silverlight exception user-controls itemscontrol