簡體   English   中英

如何在 UserControl 中使用 ContentPresenter

[英]How to use a ContentPresenter inside a UserControl

我想創建一個 UserControl(在這種情況下是一個帶有定義背景顏色的方形按鈕),它可以托管它自己的內容。

用戶控件:

<UserControl x:Class="SGDB.UI.Controls.ModernButton"
         xmlns:local="clr-namespace:SGDB.UI.Controls"
         xmlns:converter="clr-namespace:SGDB.UI.Converter"
         x:Name="_modernButton">
<Button>
    <Button.Resources>
        <converter:EnumToColorConverter x:Key="ColorConverter"/>
    </Button.Resources>
    <Button.Template>
        <ControlTemplate>
            <Border Width="{Binding Size, ElementName=_modernButton}" Height="{Binding Size, ElementName=_modernButton}" BorderBrush="Black" BorderThickness="0.8,0.8,3,3">
                <Grid Background="{Binding BackgroundColor, ElementName=_modernButton, Converter={StaticResource ColorConverter}}">
                    <ContentPresenter/>
                </Grid>
            </Border>
        </ControlTemplate>
    </Button.Template>
</Button>

現在,如您所料,如果我在 MainView 中使用此控件,則一切正常,直到我定義了一些內容。

使用:

<control:ModernButton Size="200" BackgroundColor="Light">
    TEST
</control:ModernButton>

在這種情況下,“TEST”將覆蓋 UserControl 的整個內容(整個按鈕模板)。 我猜這是因為 UserControl 中的 Button 本身被定義為“內容”,並且在定義新內容時它會被覆蓋。

所以最后一個問題是:是否有可能實現我正在尋找的東西? 如果是:如何? 如何將我在 MainView 中定義的內容“重定向”到我的按鈕模板中的自定義 ContentPresenter 而不是 UserControls 的 ContentPresenter 中?

如果可能,我不想創建一個新的 dp-propery 來托管我的內容,例如:

<controls:MordernButton Size="200" BackgroundColor="Light">
    <controls:ModernButton.Content>
        I don't want this, if possible
    </controls:ModernButton.Content>
</controls:ModernButton>

使用ContentPropertyAttribute指示 xaml 設置此屬性而不是實際的 Content 屬性。

[ContentProperty("InnerContent")]
public partial class ModernButton : UserControl
{
    public ModernButton()
    {
        InitializeComponent();
    }

    public static readonly DependencyProperty InnerContentProperty =
        DependencyProperty.Register("InnerContent", typeof(object), typeof(ModernButton));

    public object InnerContent
    {
        get { return (object)GetValue(InnerContentProperty); }
        set { SetValue(InnerContentProperty, value); }
    }
}

然后在您的 xaml 中,綁定 Content Presenter 以改用 InnerContent 屬性。

<ContentPresenter Content="{Binding InnerContent, ElementName=_modernButton}"/>

這樣您就可以在不替換實際內容的情況下執行以下操作。

<control:ModernButton Size="200" BackgroundColor="Light">
    TEST
</control:ModernButton>

我們開始吧。

<UserControl x:Class="SGDB.UI.Controls.ModernButton"
     xmlns:local="clr-namespace:SGDB.UI.Controls"
     xmlns:converter="clr-namespace:SGDB.UI.Converter"
     x:Name="_modernButton">

    <UserControl.Template>
        <ControlTemplate TargetType="UserControl">
            <Button Content="{TemplateBinding Content}">
                 <Button.Resources>
                    <converter:EnumToColorConverter x:Key="ColorConverter"/>
                  </Button.Resources>
            <Button.Template >
                <ControlTemplate TargetType="Button">
                    <Border Width="{Binding Size,
                                    ElementName=_modernButton}"
                    Height="{Binding Size,
                                     ElementName=_modernButton}"
                    BorderBrush="Black"
                    BorderThickness="0.8,0.8,3,3">
                        <Grid Background="{Binding BackgroundColor, ElementName=_modernButton, Converter={StaticResource ColorConverter}}">
                            <ContentPresenter />
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Button.Template>
            </Button>
        </ControlTemplate>
    </UserControl.Template>
</UserControl>

讓我們假設您的 UserControl 是:

<UserControl x:Class="QuickAndDirtyAttempt.Decorator" ....
      <UserControl.Template>
        <ControlTemplate TargetType="{x:Type local:Decorator}">
          <StackPanel Orientation="Vertical">
            <Label>Foo</Label>
            <ContentPresenter/>
            <Label>Bar</Label>
          </StackPanel>
        </ControlTemplate>
      </UserControl.Template>
</UserControl>

請注意模板上的 TargetType 屬性:如果沒有它,項目將很容易編譯,但 ContentPresenter 將無法工作。 然后:

<Window ... >
    <StackPanel Orientation="Vertical">
        <local:Decorator>
            <Label Background="Wheat">User supplied content here</Label>
        </local:Decorator>
    </StackPanel>
</Window> 

我強烈建議您在執行任何操作之前閱讀此內容

簡單; 只需繞過並替換 UserControl 的模板。

  <UserControl.Template>
        <ControlTemplate TargetType="{x:Type UserControl}">
            <Button Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}">
                <Button.Resources>
                   <converter:EnumToColorConverter x:Key="ColorConverter"/>
                </Button.Resources>
                <Button.Template>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Border Width="{Binding Size,
                                        ElementName=_modernButton}"
                        Height="{Binding Size,
                                         ElementName=_modernButton}"
                        BorderBrush="Black"
                        BorderThickness="0.8,0.8,3,3">
                            <Grid Background="{Binding BackgroundColor, ElementName=_modernButton, Converter={StaticResource ColorConverter}}">
                                <ContentPresenter />
                            </Grid>
                        </Border>
                    </ControlTemplate>
                </Button.Template>
            </Button>
        </ControlTemplate>
    </UserControl.Template>

所有用戶控件都是(至少是 XAML 及其模板的術語),是一個帶有 ContentPresenter 的邊框。 ContentPresenter 是唯一重要的部分,真的。

所以你要做的就是刪除它的 Template 並將 UserControl 的 Content 屬性輸入一些不同的東西; 在這種情況下,您的按鈕。

這是其他控件中制作用戶控件與將某些控件推用戶控件之間的區別。 使用戶控件脫離其他控件可為您提供更多功能。

我的對話框示例

<UserControl
x:Class="CyberpunkModManager.Controls.DialogBox"
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:local="clr-namespace:CyberpunkModManager.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="450"
d:DesignWidth="800"
Foreground="{StaticResource ThemeForeground}"
mc:Ignorable="d">
<UserControl.Template>
    <ControlTemplate TargetType="UserControl">
        <Grid Background="{StaticResource ThemeTransparentColor}">
            <Border
                MinWidth="400"
                Padding="12"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Background="{StaticResource ThemeElement}"
                CornerRadius="4">
                <ContentPresenter />
            </Border>
        </Grid>
    </ControlTemplate>
</UserControl.Template>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM