有趣的問題。我寫了一個DockPanelWithOverlay組件做的工作:
我這裏選擇的是CustomControl因爲我想有面板的繼承。 但面板沒有可以更改的模板。 所以我寫控制的自定義控件繼承了自定義模板 但用戶控件會很好地工作,我認爲(我沒有嘗試要誠實)
編輯用戶控件是不太好,因爲它繼承了ContentControl中。 所以它只能有一個孩子。
DockPanelWithOverlay的目標是有很多孩子。 所以我認爲UserControl並不是最好的繼承方式。 當你想在xaml中提供一些內容時,用戶控件會更好,主要是靜態的,不能由控件的用戶自定義。
編輯
末來組織內容的tempalte裏面,我用了一個網格。
這兩個組件的順序很重要。 這是繪圖順序。
網格允許將兩個組件放在同一個地方:
裏面會有Overlay控件和一個底層DockPanel。
DockPanelWithOverlay
.. |
.. | - 控制模板
...... |
...... | -Grid
.......... |
.......... | --DockPanel
.......... | --OverlayControl
具有模板的更容易使從DockPanelWithOverlay一些結合模板的控件屬性。 (要生成CustomControl,創建WPFCustom控件庫項目)主題\ generic.xaml的
摘錄庫:
<Style TargetType="{x:Type local:DockPanelWithOverlay}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:DockPanelWithOverlay}">
<!-- the grid allows to put two components at the same place -->
<Grid >
<DockPanel x:Name="dockPanel" />
<ContentControl x:Name="overlayControl" Visibility="{TemplateBinding OverlayVisibility}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
控制的繼承允許使用模板來創建小的UI元素的層次結構。
一些依賴屬性必須添加用於使結合:
- 疊加,用於提供一些UI元素或字符串覆蓋內容
- OverlayVisibility用於隱藏/顯示覆蓋
這裏是DockPanelWithOverlay的代碼:
(注意剛剛調用模板組件後調用的OnApplytemplate)
// Children is the property that will be valued with the content inside the tag of the control
[ContentProperty("Children")]
public class DockPanelWithOverlay : Control
{
static DockPanelWithOverlay()
{
// Associate the control with its template in themes/generic.xaml
DefaultStyleKeyProperty.OverrideMetadata(typeof(DockPanelWithOverlay), new FrameworkPropertyMetadata(typeof(DockPanelWithOverlay)));
}
public DockPanelWithOverlay()
{
Children = new UIElementCollection(this, this);
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
// once the template is instanciated, the dockPanel and overlayCOntrol can be found from the template
// and the children of DockPanelWithOverlay can be put in the DockPanel
var dockPanel = this.GetTemplateChild("dockPanel") as DockPanel;
if (dockPanel != null)
for (int i = 0; i < Children.Count;)
{
UIElement elt = Children[0];
Children.RemoveAt(0);
dockPanel.Children.Add(elt);
}
}
// Here is the property to show or not the overlay
public Visibility OverlayVisibility
{
get { return (Visibility)GetValue(OverlayVisibilityProperty); }
set { SetValue(OverlayVisibilityProperty, value); }
}
// Here is the overlay. Tipically it could be a Texblock,
// or like in our example a Grid holding a TextBlock so that we could put a semi transparent backround
public Object Overlay
{
get { return (Object)GetValue(OverlayProperty); }
set { SetValue(OverlayProperty, value); }
}
// Using a DependencyProperty as the backing store for OverlayProperty.
// This enables animation, styling, binding, etc...
public static readonly DependencyProperty OverlayProperty =
DependencyProperty.Register("Overlay", typeof(Object), typeof(DockPanelWithOverlay), new PropertyMetadata(null));
public static readonly DependencyProperty OverlayVisibilityProperty =
DependencyProperty.Register("OverlayVisibility", typeof(Visibility), typeof(DockPanelWithOverlay), new PropertyMetadata(Visibility.Visible));
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public UIElementCollection Children
{
get { return (UIElementCollection)GetValue(ChildrenProperty); }
set { SetValue(ChildrenProperty, value); }
}
public static readonly DependencyProperty ChildrenProperty =
DependencyProperty.Register("Children", typeof(UIElementCollection), typeof(DockPanelWithOverlay), new PropertyMetadata(null));
}
使用DockPanelWithOverlay:
<lib:DockPanelWithOverlay x:Name="dockPanelWithOverlay1"
OverlayVisibility="Visible"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Button Content="Top" Height="50" DockPanel.Dock="Top" Background="Red"/>
<Button Content="Bottom" Height="50" DockPanel.Dock="Bottom" Background="Yellow"/>
<Button Content="Left" Width="50" DockPanel.Dock="Left" Background="Pink"/>
<Button Content="Right" Width="50" DockPanel.Dock="Right" Background="Bisque"/>
<Button Content="Center" Background="Azure"/>
<lib:DockPanelWithOverlay.Overlay>
<Grid Background="#80404080">
<TextBlock Text="Overlay" FontSize="80" Foreground="#FF444444" HorizontalAlignment="Center" VerticalAlignment="Center" RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="-15"/>
<TranslateTransform/>
</TransformGroup>
</TextBlock.RenderTransform>
</TextBlock>
</Grid>
</lib:DockPanelWithOverlay.Overlay>
</lib:DockPanelWithOverlay>
該覆蓋可以很容易地開啓或關閉從CheckBox.IsChecked屬性例如結合進行切換。
以下是完整的工作代碼:http://1drv.ms/1NfCl9z
我覺得這是真的回答你的問題。問候
謝謝,這正是我一直在尋找的東西。 – Jason
我喜歡這個,並且會仔細研究它。謝謝Emmanuel。 – PScr