我遇到了一个问题,我在其中创建了一个包含两个内容集合的用户控件。为了简单起见,我们会说它有两个控件。
在后面的代码中我暴露了那些itemCollections,以便我可以在另一个控件中声明内容。
例如
<!-- User Control xaml -->
<UserControl>
<StackPanel Orientation="Horizontal" >
<ItemsControl x:Name="_itemsControl1" />
<ItemsControl x:Name="_itemsControl2" />
</StackPanel>
</UserControl>
//in the codebehind for user control
public partial class TwoControls
{
public ItemCollection ItemsOne { get { return _itemsControl1.Items; }}
public ItemCollection ItemsTwo { get { return _itemsControl2.Items; }}
}
<!-- Using the control in xaml later -->
<Custom:TwoControls>
<Custom:TwoControls.ItemsOne>
<TextBox />
<TextBox />
<TextBox />
<TextBox />
<TextBox />
</Custom:TwoControls.ItemsOne>
<Custom:TwoControls.ItemsTwo>
<Button />
<Button />
<Button />
<Button />
<Button />
</Custom:TwoControls.ItemsTwo>
<Custom:TwoControls>
这实际上适用于一个小问题。一旦我尝试命名任何控件,我就会收到以下错误。
<!-- Using the control in xaml later -->
<Custom:TwoControls>
<Custom:TwoControls.ItemsOne>
<TextBox x:Name="txt"/>
无法在元素'TextBox'上设置名称属性值'txt'。 'TextBox'在元素'TwoControls'的范围内,在另一个范围内定义时已经注册了名称。
如果我实际上不必命名控件,我就不会。我们有一些工具可以运行,期望将某些内容控件命名为构建过程的一部分,我需要它们具有名称。还值得注意的是,我实际上在我的TwoControls类中有几个事件,如果我要将其提取到数据模板,我认为我可以使它工作,但我必须比现在更多地工作。
关于为什么会这样做的任何输入都会很棒。
答案 0 :(得分:1)
我不想听起来很直率,但每当我遇到这个特殊的名称范围问题时,我都记得我做的事情比WinF方式更多,而不是WPF方式。对于类似于容器的控件,我更多地使用Usercontrols来控制页面控件。
建议可能是创建自定义控件而不是用户控件。
public class TwoControls: Control
{
static TwoControls( )
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( TwoControls ) , new FrameworkPropertyMetadata( typeof( TwoControls ) ) );
}
public ObservableCollection<UIElement> ItemsOne
{
get { return ( ObservableCollection<UIElement> )GetValue( ItemsOneProperty ); }
set { SetValue( ItemsOneProperty , value ); }
}
public static readonly DependencyProperty ItemsOneProperty = DependencyProperty.Register(
"ItemsOne" , typeof( ObservableCollection<UIElement> ) , typeof( TwoControls ) ,
new PropertyMetadata( new ObservableCollection<UIElement>( ) ) );
public ObservableCollection<UIElement> ItemsTwo
{
get { return ( ObservableCollection<UIElement> )GetValue( ItemsTwoProperty ); }
set { SetValue( ItemsTwoProperty , value ); }
}
public static readonly DependencyProperty ItemsTwoProperty = DependencyProperty.Register(
"ItemsTwo" , typeof( ObservableCollection<UIElement> ) , typeof( TwoControls ) ,
new PropertyMetadata( new ObservableCollection<UIElement>( ) ) );
}
//The next in your ResourceDictionary
<Style xmlns:local="clr-namespace:WPFApplication1" TargetType="{x:Type local:TwoControls}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:TwoControls}">
<StackPanel Orientation="Horizontal">
<ItemsControl ItemsSource="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ItemsOne}"/>
<ItemsControl ItemsSource="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ItemsTwo}"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
//The last in your xaml
<Custom:TwoControls x:Name="twoControls1">
<Custom:TwoControls.ItemsOne>
<TextBox x:Name="Test1"/>
<TextBox x:Name="Test2"/>
<TextBox x:Name="Test3"/>
<TextBox x:Name="Test4"/>
<TextBox x:Name="Test5"/>
</Custom:TwoControls.ItemsOne>
<Custom:TwoControls.ItemsTwo>
<Button x:Name="ButtonTest1"/>
<Button x:Name="ButtonTest2"/>
<Button x:Name="ButtonTest3"/>
<Button x:Name="ButtonTest4"/>
<Button x:Name="ButtonTest5"/>
</Custom:TwoControls.ItemsTwo>
</Custom:TwoControls>