Исключение, возникающее при привязке ItemsControl к коллекции UserControls - PullRequest
1 голос
/ 13 августа 2011

В моем приложении шаблонная форма должна отображать список пользовательских элементов управления в панели стека.Я подумал, что мог бы использовать ItemsControl в форме и связать его с коллекцией, которая предоставляет «дочерние элементы управления».Этот подход отлично работает в первый раз, когда загружается шаблонная форма, но если я внесу какие-либо изменения в коллекцию Observable дочерних пользовательских контроллеров, я получу исключение «Значение не попадает в ожидаемый диапазон».

Я посмотрелчерез много сообщений, но ни одно из решений, кажется, не сработало.Я вставляю пример кода, который показывает проблему, о которой я говорю.Пример кода имеет

  1. Главная страница с ItemsCOntrol в нем.Элемент Itemscontrol связан с коллекцией Observable, имеющей тип AnyControl.

  2. Класс AnyControl имеет открытое свойство AttachedControl.AttachedControl - это тип объекта.

Когда загружается главная страница, я создаю 2 экземпляра AnyControl и устанавливаю для свойства AttachedControl экземпляры текстовых полей.

На главной странице 3 кнопки

  1. Показать все.который устанавливает текст данных главной страницы и два текстовых поля отображаются в форме.
  2. Удалить второй элемент управления.нажатие этой кнопки удаляет вторую запись из ObservableCollection, и второе текстовое поле исчезает.
  3. Восстановить второй контроль.нажатие на эту кнопку добавляет вторую запись обратно в коллекцию Observable.Логически второе текстовое поле должно отображаться в форме, но вместо этого я получаю исключение.

Код начинается здесь ..... 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 голосов
/ 13 августа 2011

Написал пользовательский элемент управления для решения этой проблемы. Так как все, что я хотел, это показать пользовательские элементы управления в «родительской» форме, я закончил тем, что создал пользовательский элемент управления панели. Добавил свойство зависимости с именем ItemsSource к нему. Обработчик этого свойства добавляет пользовательские элементы управления в своей коллекции в коллекцию CHildren панели.

@ ColinE, перед тем, как добавить дочерний элемент управления на панель, я проверю, не является ли он дочерним элементом другой панели. Если это так, я получаю ссылку на элемент управления родительской панели и удаляю элемент управления из дочерней коллекции этой родительской панели.

Кажется, работает просто отлично.

Спасибо за комментарии. A

...