我一直致力于控制一段时间,可用于在我们的应用程序中重复布局。它工作得很好,但问题是布局控件中的控件没有参与逻辑树。
这是一个自定义控件,左侧标题,右侧标题,正文和标准页脚。
Generic.xaml:
<Style TargetType="{x:Type local:FrameControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:FrameControl}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Border VerticalAlignment="Top" Height="50" Background="LightGray"/>
<DockPanel Background="{TemplateBinding HeaderColor}">
<ItemsControl ItemsSource="{TemplateBinding HeaderLeftContent}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel DockPanel.Dock="Left" FlowDirection="LeftToRight" HorizontalAlignment="Left"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<ItemsControl ItemsSource="{TemplateBinding HeaderRightContent}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel DockPanel.Dock="Right" Height="40"
Margin="5, 5, 5, 0" VerticalAlignment="Top"
Orientation="Horizontal" FlowDirection="RightToLeft"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</DockPanel>
<Border BorderThickness="1" BorderBrush="Black" Margin="0,49,0,0" Background="White">
<ItemsControl ItemsSource="{TemplateBinding BodyContent}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<DockPanel Background="White" Margin="5"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Border>
<Border VerticalAlignment="Bottom" Height="0" Background="LightGray"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
FrameControl.cs
public class FrameControl : Control
{
public Brush HeaderColor
{
get { return (Brush)GetValue(HeaderColorProperty); }
set { SetValue(HeaderColorProperty, value); }
}
public static readonly DependencyProperty HeaderColorProperty =
DependencyProperty.Register("HeaderColor", typeof(Brush), typeof(FrameControl), new UIPropertyMetadata(null));
public Collection<Object> HeaderLeftContent
{
get { return (Collection<Object>)GetValue(HeaderLeftContentProperty); }
set { SetValue(HeaderLeftContentProperty, value); }
}
public static readonly DependencyProperty HeaderLeftContentProperty =
DependencyProperty.Register("HeaderLeftContent", typeof(Collection<Object>), typeof(FrameControl),
new UIPropertyMetadata(null));
public Collection<Object> HeaderRightContent
{
get { return (Collection<Object>)GetValue(HeaderRightContentProperty); }
set { SetValue(HeaderRightContentProperty, value); }
}
public static readonly DependencyProperty HeaderRightContentProperty =
DependencyProperty.Register("HeaderRightContent", typeof(Collection<Object>), typeof(FrameControl),
new UIPropertyMetadata(null));
public Collection<Object> BodyContent
{
get { return (Collection<Object>)GetValue(BodyContentProperty); }
set { SetValue(BodyContentProperty, value); }
}
public static readonly DependencyProperty BodyContentProperty =
DependencyProperty.Register("BodyContent", typeof(Collection<Object>), typeof(FrameControl),
new UIPropertyMetadata(null));
static FrameControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(FrameControl), new FrameworkPropertyMetadata(typeof(FrameControl)));
}
public FrameControl()
{
SetValue(HeaderLeftContentProperty, new Collection<Object>());
SetValue(HeaderRightContentProperty, new Collection<Object>());
SetValue(BodyContentProperty, new Collection<Object>());
}
}
使用示例
<fc:FrameControl>
<fc:FrameControl.HeaderLeftContent>
<Label Content="Left content of the header"/>
</fc:FrameControl.HeaderLeftContent>
<fc:FrameControl.HeaderRightContent>
<Button>
<TextBlock Text="Example button"/>
</Button>
<ComboBox SelectedIndex="0">
<ComboBoxItem Content="Filter A"/>
<ComboBoxItem Content="Filter B"/>
<ComboBoxItem Content="Filter C"/>
</ComboBox>
</fc:FrameControl.HeaderRightContent>
<fc:FrameControl.BodyContent>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="name"/>
<TextBox Grid.Row="0" Grid.Column="2"/>
<Label Grid.Row="1" Grid.Column="0" Content="Type name"/>
<TextBox Grid.Row="1" Grid.Column="2" />
<Label Grid.Row="2" Grid.Column="0" Content="Keyword"/>
<TextBox Grid.Row="2" Grid.Column="2"/>
<Label Grid.Row="3" Grid.Column="0" Content="Parameter"/>
<ComboBox Grid.Row="4" Grid.Column="0" SelectedIndex="0">
<ComboBoxItem Content="Width"/>
<ComboBoxItem Content="Height"/>
</ComboBox>
<ComboBox Grid.Row="4" Grid.Column="1" SelectedIndex="0">
<ComboBoxItem Content="..."/>
<ComboBoxItem Content="="/>
<ComboBoxItem Content="<"/>
<ComboBoxItem Content=">"/>
</ComboBox>
<TextBox Grid.Row="4" Grid.Column="2"/>
</Grid>
</fc:FrameControl.BodyContent>
</fc:FrameControl>
我尝试使用不同类型的属性来保存不同区域的元素,如UIElementCollection,但没有区别。我也尝试手动将控件添加到逻辑树中,但我没有成功。我错过了什么吗?
答案 0 :(得分:0)
您说实际的问题是无法使用此控件使用ElementName进行绑定。无法以这种方式接近FrameControl内部的元素。但是,该问题与可视化树完全无关。视觉树中的那些元素是,但您无法访问它们,因为它们是在ControlTemplate
内定义的。
您可以使用ControlTemplate.FindName
method为您找到元素。但是,您需要有ControlTemplate
已应用的元素以及ControlTemplate
中的命名元素:
// Assuming that your DockPanel in the ControlTemplate was named DockPanel
DockPanel dockPanel =
frameControl.Template.FindName("DockPanel", frameControl) as DockPanel;
if (dockPanel != null) // You must check for null
{
DoSomethingHereWith(dockPanel);
}
请参阅链接页面以获取更多帮助。