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



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

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

  1. 包含ItemsCOntrol的主页。items控件绑定到

  2. 类AnyControl有一个公共属性AttachedControl。的

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

主页有3个按钮

  1. 显示所有。哪个设置主页和两个页面的数据上下文文本框显示在表单上。
  2. 删除第二个控件。点击这个按钮从ObservableCollection和第二个文本框消失。
  3. 恢复第二控制。点击这个按钮将第二个条目添加回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>

非常感谢任何帮助。谢谢

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

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

它似乎工作得很好。

谢谢你的评论。

最新更新