在我的应用程序中,模板化的表单需要在stackpanel中显示用户控件列表。我想我可以在表单上使用ItemsControl,并将其绑定到一个公开"子用户控件"的集合。这种方法在模板化表单加载时第一次工作得很好,但如果我对子usercontrols的Observable集合进行任何更改,我就会得到一个异常"值不属于预期范围"。
我看了很多帖子,但没有一个解决方案似乎已经工作。我正在粘贴一个示例代码,显示我正在谈论的问题。示例代码中有
-
包含ItemsCOntrol的主页。items控件绑定到
-
类AnyControl有一个公共属性AttachedControl。的
当Mainpage加载时,我创建了2个AnyControl实例,并将AttachedControl属性设置为Textboxes实例。
主页有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>
非常感谢任何帮助。谢谢
写了一个自定义控件来解决这个问题。因为我想要的只是在"父"表单中显示用户控件,所以我最终创建了一个自定义面板控件。添加了一个名为ItemsSource的依赖属性。此属性的处理程序将其集合中的自定义控件添加到面板的CHildren集合中。
@ColinE,我确实确保在向面板添加子控件之前,我检查它是否是另一个面板的子控件。如果是,则获取对其父面板控件的引用,并从其父面板的子集合中删除该控件。
它似乎工作得很好。
谢谢你的评论。