Содержимое UserControl пусто при попытке использовать ContentPresenter внутри DataTemplate

У меня есть основной абстрактный класс только для кода BaseImpostorButton, наследующий UserControl. У меня есть дочерний класс ClickableImageButton с xaml и кодом программной части.

Я использую следующий стиль с ControlTemplate:

<Style TargetType="{x:Type local:ClickableImageButton}">
    <Setter Property="ToolTipService.InitialShowDelay" Value="0"/>
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:ClickableImageButton}">
                <StackPanel Margin="{TemplateBinding Margin}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}">
                    <ContentPresenter
                        Content="{TemplateBinding Content}"
                        ContentTemplate="{TemplateBinding ContentTemplate}" />
                </StackPanel>
            </ControlTemplate>                
        </Setter.Value>
    </Setter>
</Style>

При использовании в ListView в качестве необработанного ListViewItem мой ClickableImageButton отображается правильно.

НО: при использовании его в представлении списка с ItemTemplate DataTemplate ClickableImageButton больше не отображается... как если бы содержимое было пустым внутри DataTemplate.

Решение, которое я нашел, состояло в том, чтобы написать DependencyProperty ButtonContent на BaseImpostorButton и явно установить его в xaml.

Но может ли кто-нибудь объяснить этот вопрос?

РЕДАКТИРОВАТЬ: вот 2 разных xaml. Тот, который правильно показывает базовое изображение (ClickableImage - это изображение)

<ListView Grid.Row="1" Name="ListViewSections" ItemsSource="{Binding Path=Sections}" Background="{x:Null}" SizeChanged="ListViewSections_SizeChanged">                    
            <ListViewItem>
<Grid MaxWidth="600">
                        <Grid.RowDefinitions>
                            <RowDefinition/>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition MaxWidth="150"/>
                            <ColumnDefinition />
                        </Grid.ColumnDefinitions>
                        <TextBlock Grid.Row="0" Grid.ColumnSpan="2" Text="{Binding Path=Titre}" Margin="5,0,5,0" FontSize="18" FontWeight="Bold" Foreground="White" TextWrapping="Wrap" FontFamily="Arial" HorizontalAlignment="Left" />
                        <local:ClickableImageButton Grid.Row="1" Tag="{Binding Path=Id}" Grid.Column="0" ImpostorClick="Image_Click" Margin="10">
                            <local:ClickableImageButton.Content>
                                <local:ClickableImage Source="Content/tada.png" />
                            </local:ClickableImageButton.Content>
                        </local:ClickableImageButton>
                        <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=Texte}" Margin="10,0,10,0" FontSize="16" Foreground="White" TextWrapping="Wrap" FontFamily="Arial" VerticalAlignment="Center" HorizontalAlignment="Left" />
                    </Grid>                                       
            </ListViewItem>                
        </ListView>

И тот, который не работает

<ListView Grid.Row="1" Name="ListViewSections" ItemsSource="{Binding Path=Sections}" Background="{x:Null}" SizeChanged="ListViewSections_SizeChanged">                    
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Grid MaxWidth="600">
                        <Grid.RowDefinitions>
                            <RowDefinition/>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition MaxWidth="150"/>
                            <ColumnDefinition />
                        </Grid.ColumnDefinitions>
                        <TextBlock Grid.Row="0" Grid.ColumnSpan="2" Text="{Binding Path=Titre}" Margin="5,0,5,0" FontSize="18" FontWeight="Bold" Foreground="White" TextWrapping="Wrap" FontFamily="Arial" HorizontalAlignment="Left" />
                        <local:ClickableImageButton Grid.Row="1" Tag="{Binding Path=Id}" Grid.Column="0" ImpostorClick="Image_Click" Margin="10">
                            <local:ClickableImageButton.Content>
                                <local:ClickableImage Source="Content/tada.png" />
                            </local:ClickableImageButton.Content>
                        </local:ClickableImageButton>
                        <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=Texte}" Margin="10,0,10,0" FontSize="16" Foreground="White" TextWrapping="Wrap" FontFamily="Arial" VerticalAlignment="Center" HorizontalAlignment="Left" />
                    </Grid>
                </DataTemplate>                    
            </ListView.ItemTemplate>                
        </ListView>

person Loul G.    schedule 18.01.2013    source источник
comment
Почему вы исходите из пользовательского контроля, если вы его не используете? Я бы советовал извлекать напрямую из ContentControl. И ContentPresenter внутри шаблона элемента управления автоматически принимает привязки шаблонов для содержимого, ContentTemplate и ContentTemplateSelector... таким образом, ‹ContentPresenter /› должно быть достаточно.   -  person dowhilefor    schedule 18.01.2013
comment
Получение базового абстрактного класса от ContentControl ничего не меняет. И UserControl - это ContentControl   -  person Loul G.    schedule 18.01.2013
comment
Вы написали <local:ClickableImageButton Content="{Binding}" ... /> в своем DataTemplate?   -  person Clemens    schedule 18.01.2013
comment
Не совсем так : <local:ClickableImageButton> <local:ClickableImageButton.Content><local:ClickableImage Source="{Binding Path=Image.Source}" /></local:ClickableImageButton.Content></local:ClickableImageButton>   -  person Loul G.    schedule 18.01.2013
comment
ClickableImage — это класс только для кода, который я создаю из данных XML. Этот код работает, когда он находится в области ListViewItem, но не в области ItemTemplate/DataTemplate.   -  person Loul G.    schedule 18.01.2013
comment
Возможно, вам следует отредактировать свой вопрос и добавить соответствующие части XAML для обоих случаев внутри ListViewItems и в DataTemplate.   -  person Clemens    schedule 18.01.2013
comment
Помимо моего комментария, вы знаете, что вы не можете использовать шаблоны с пользовательскими элементами управления, не так ли? См. примечания это.   -  person dowhilefor    schedule 19.01.2013
comment
@dowhilefor: Вы абсолютно правы! MDSN говорит Before deriving from UserControl, consider that your control will not support templates. Но это несколько странно... Это подразумевает, что UserControl не имеет того же поведения, что и его базовый класс...   -  person Loul G.    schedule 20.01.2013
comment
@LoulG Вот что я имел в виду, говоря, почему вы исходите из пользовательского контроля, если вы его не используете. У него есть шаблон, но фиксированный шаблон, который вы заполняете с помощью XAML, обычно генерируемого IDE. Вы не использовали это, вместо этого должно быть достаточно производного от ContentControl и установки DefaultStyleKey.   -  person dowhilefor    schedule 20.01.2013
comment
@dowhilefor: Теперь я понимаю, что вы имеете в виду. Я пока не могу тестировать изменения, но я проверю как можно скорее.   -  person Loul G.    schedule 20.01.2013
comment
@dowhilefor: Привет. Что касается первой части кода выше, я только что очистил презентатор контента <ContentPresenter />. Я также получил свой BaseImpostorButton от ContentControl вместо UserControl. Элемент управления по-прежнему не отображается при использовании внутри шаблона...   -  person Loul G.    schedule 28.01.2013
comment
@dowhilefor: и я также установил ctor BaseImpostorButton в статический и поставил FrameworkElement.DefaultStyleKeyProperty.OverrideMetadata(typeof(BaseImpostorButton), new FrameworkPropertyMetadata(typeof(BaseImpostorButton)));   -  person Loul G.    schedule 28.01.2013
comment
@LoulG. пожалуйста, используйте snoop, чтобы точно проверить, чего не хватает в вашем визуальном дереве. Проверьте вывод на наличие предупреждений или ошибок. Где вы разместили свой стиль по умолчанию? В ресурсе xaml? В app.xaml? В универсальном.xaml? Убедитесь, что у него нет имени. Убедитесь, что размер не будет вычисляться до (0, 0) в зависимости от содержимого и используемого компоновщика, снова попробуйте snoop, чтобы проверить это. Для меня работает производное от ContentControl, установка DefaultStyleKey, создание правильного стиля по умолчанию (без имени) внутри generic.xaml или app.xaml.   -  person dowhilefor    schedule 28.01.2013
comment
@dowhilefor: На самом деле стиль находится во внешнем словаре, и только для TargetType установлено значение ClickableImageButton. На самом деле это работает и при наследовании от ContentControl, устанавливая DefaultStyleKey. Но это не проблема. Это работает только в том случае, если содержимое элемента управления по умолчанию абсолютно пусто.   -  person Loul G.    schedule 28.01.2013
comment
У кого-нибудь есть объяснение такому поведению?   -  person Loul G.    schedule 29.01.2013


Ответы (1)


Итак, наконец, я заставляю его работать. Это было не из-за того, что я был производным от UserControl.

Поэтому я продолжал получать BaseImpostorButton из UserControl, я очищал ContentPresenter в ControlTemplate (<ContentPresenter />).

Мне не нужно было устанавливать DefaultStyleKey.

Мне просто нужно было удалить любой контент из файла xaml дочернего класса. Действительно, когда я создал свой дочерний UserControl, я не удалил добавленный контент по умолчанию, то есть <Grid />. Удаление этого просто решило все мои проблемы.

Похоже, содержимое по умолчанию не переопределяется, когда мы пытаемся установить его из шаблонного контекста, а только при установке из нешаблонного контекста.

т.е. прежний код:

<sk:BaseImpostorButton x:Class="Compteur_3D.ClickableImageButton"
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
           xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
           xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  mc:Ignorable="d"
         d:DesignHeight="300" d:DesignWidth="300">
<Grid/>
</sk:BaseImpostorButton>

исправлен код:

<sk:BaseImpostorButton x:Class="Compteur_3D.ClickableImageButton"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"              mc:Ignorable="d"
         d:DesignHeight="300" d:DesignWidth="300">
</sk:BaseImpostorButton>

Изменить: во время выполнения мой элемент ClickableImageButton имеет правильное содержимое (т.е. ClickableImage), когда <Grid /> удалено. НО, когда <Grid /> не удален, мой ClickableImageButton имеет пустую сетку в качестве содержимого... Как будто это <Grid /> не было переопределено при установке содержимого в:

<local:ClickableImageButton ImpostorClick="Image_Click" Margin="10">
                            <local:ClickableImageButton.Content>
                                <local:ClickableImage Source="{Binding Path=Image.Source}" />
                            </local:ClickableImageButton.Content>
                        </local:ClickableImageButton>

Изменить: профиль клиента Target Framework 4

person Loul G.    schedule 28.01.2013