2016-04-06 4 views
6

Я хотел бы создать UserControl (в данном случае квадратную кнопку с определенными Backgroundcolors), которая может размещать собственный контент.Как использовать ContentPresenter внутри 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 Everthing работает нормально, пока я не определимся содержимое.

Использование:

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

В этом случае "TEST" будет перекрывать все содержимое UserControl (все кнопки Template). Я предполагаю, что это происходит, потому что кнопка внутри UserControl определена как «контент» сама по себе, и она будет переопределяться при определении нового содержимого.

Итак, последний вопрос: возможно ли достичь того, что я ищу? если да: как? Как я могу «перенаправить» содержимое, которое я определяю в своем MainView, в самоопределенный ContentPresenter внутри шаблона кнопок вместо ContentPresenter UserControls?

Если это возможно, я не хочу, чтобы создать новый дп-Собственость в котором находится мой контент, например:

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

Вы хотите сказать, что не хотите создавать новые dp для этого? – Gopichandar

+0

Правильно - если возможно, конечно. – C4p741nZ

+0

@ Chill-X См. Мой ответ ниже. Дайте мне знать, если вы столкнулись с какими-либо проблемами. – Gopichandar

ответ

5

Здесь мы идем.

<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> 
+0

Сначала это показалось очень хорошим - но при передаче некоторого контента («ТЕСТ» или ) ничего не появляется - Управление остается пустым (за исключением собственного цвета) – C4p741nZ

+0

Вот и все - не могли бы вы объяснить, почему TargetType Button Button оказал такое большое влияние на ContentPresenter? И если вы на нем, может быть, вы могли бы объяснить, почему Button Templatebinding перестает очищать WPF от всего содержимого при передаче некоторого контента в элемент управления? Спасибо заранее – C4p741nZ

+1

Это будет большая тема для покрытия. Может быть [это] (http://stackoverflow.com/a/3632926/2819451) отвечает на ваш первый вопрос. – Gopichandar

2

Давайте предположим, что Youre 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> 

Я настоятельно рекомендую вам read this перед реализацией ничего

+0

Я прочитал это, но прочитал часть, в которой говорится: «Без TargetType проект будет с удовольствием компилироваться, но ContentPresenter не будет работать». Вы заслуживаете моего повышения, потому что CodeProject объясняет, почему не следует использовать мое решение :) – C4p741nZ

2

Простой; Просто обходите и замените Шаблон 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 является единственной важной частью.

Итак, все, что вы делаете, это кишка из своего шаблона и кормит свойство Content, которое пользовательский элемент управления имеет в чем-то совсем другом; в этом случае, ваша кнопка.

В этом разница между созданием UserControl из других элементов управления и толкая некоторые элементы управления в пользовательского элемента управления. Создание пользовательского контроля из других элементов управления дает вам гораздо больше мощности.

+1

Думайте, что это может сработать, если второй тип ControlTemplate будет «Button». – C4p741nZ

+0

О да, как я пропустил это? - Отредактировал его. – Logan

10

Используйте команду 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> 
+2

Работает тоже. Но я хотел знать, как все работает в XAML - мне действительно не нравится украшать Code с атрибутами. – C4p741nZ

+0

Удивительный совет! поскольку это не переопределение шаблона, вам разрешено легко определять имена и ссылки с кодом –

Смежные вопросы