将ItemsControl绑定到UserControls集合时抛出异常

时间:2011-08-12 20:05:14

标签: .net silverlight exception user-controls itemscontrol

在我的应用程序中,模板化表单需要在stackpanel中显示用户控件列表。我想我可以在表单上使用ItemsControl并将其绑定到一个公开“child usercontrols”的集合。这种方法在模板化表单加载时第一次正常工作,但如果我对子用户控件的Observable集合进行任何更改,我会得到一个异常“值不在预期范围内”。

我看了很多帖子但是没有一个解决方案似乎有效。我正在粘贴一个示例代码,显示我正在谈论的问题。示例代码有

  1. 主页包含ItemsCOntrol。 Itemscontrol绑定到 AnyControl类型的Observablecollection。

  2. Class AnyControl有一个公共属性AttachedControl。该 AttachedControl是类型对象。

  3. 当Mainpage加载时,我创建了2个AnyControl实例,并将AttachedControl属性设置为Textboxes的实例。

    主页有3个按钮

    1. 全部显示。它设置主页的datacontext和两个 文本框显示在表单上。
    2. 删除第二个控件。点击这个 按钮从ObservableCollection和。中删除第二个条目 第二个文本框消失。
    3. 恢复第二个控制。点击这个 按钮将第二个条目添加回Observable Collection。 从逻辑上讲,第二个文本框应该显示在表单上,​​而是显示在表单上 我得到了例外。
    4. 代码从这里开始...... 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>
      

      非常感谢任何帮助。 谢谢 甲

1 个答案:

答案 0 :(得分:0)

写了一个自定义控件来解决这个问题。因为我想要的只是在“父”表单中显示usercontrols,所以我最终创建了一个自定义面板控件。添加了一个名为ItemsSource的依赖项属性。此属性的处理程序将其集合中的自定义控件添加到面板的CHildren集合中。

@ColinE,我确实确保在向面板添加子控件之前检查它是否是另一个面板的子项。如果是,我获取对其父面板控件的引用,并从该父面板的子集合中删除该控件。

似乎工作得很好。

感谢您的评论。 甲