Привязка данных UserControl внутри ListView завершается неудачно - PullRequest
0 голосов
/ 17 марта 2020

У меня есть пользовательский элемент управления, здесь упрощенно:

<UserControl x:Class="WPF.TestControl"
             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" 
             xmlns:local="clr-namespace:WPF"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <ContentPresenter Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}" />
    </Grid>
</UserControl>

При использовании:

<local:TestControl Grid.Row="0">
    <Border BorderBrush="Red" BorderThickness="1">
        <TextBlock Text="{Binding Path=Message, Mode=OneWay}"/>
    </Border>
</local:TestControl>

Пока все хорошо, что работает.

Однако, когда используется как часть DataTemplate для ListView, привязка больше не работает:

<ListView ItemsSource="{Binding Path=Items}" Grid.Row="2">
    <ListView.Resources>
        <DataTemplate DataType="{x:Type local:TestViewModel}">
            <local:TestControl>
                <TextBlock Text="{Binding Path=Message, Mode=OneWay}"/>
            </local:TestControl>
        </DataTemplate>
    </ListView.Resources>
</ListView>

Какие заклинания необходимы для работы привязки данных выше?

1 Ответ

1 голос
/ 17 марта 2020

Вы создаете бесконечное l oop.
UserControl уже является ContentControl, как оно происходит из него. Поэтому, пока вы не переопределите его ControlTemplate, вы не должны добавлять к нему ContentPresenter, который привязывается к TemplatedParent при использовании внутри шаблона.

Триггер этого страдания это TemplatedParent привязка. TestControl является частью шаблона. Шаблон применяется к ListViewItem, который поэтому является шаблонным родителем TestControl.

Теперь значением источника привязки ContentPresenter внутри TestControl является значение свойства ListViewItem.Content, которое содержит сам TestControl. Таким образом, вы добавляете шаблонного родителя ListViewItem.Content, который является TestControl, к ContentPresenter из TestControl, который теперь содержит тот же TestControl (сам по себе), который связывает шаблонного родителя ListViewItem.Content, который это TestControl, ContentPresenter из TestControl, который теперь содержит тот же TestControl (сам), который связывает шаблонного родителя ... StackOverflow.

Если вы хотите использовать UserControl как ContentControl, т. Е. Для отображения визуальных элементов других «внешних» элементов управления, то используйте его как ContentCobtrol:

TestControl

<UserControl x:Class="TestControl">
</UserControl>

DataTemplate

<DataTemplate DataType="{x:Type local:TestViewModel}">
  <local:TestControl>
    <TextBlock Text="{Binding Path=Message, Mode=OneWay}"/>
  </local:TestControl>
</DataTemplate>

Или, если контент более сложный и продвинутый, чем простая презентация, вы должны переопределить ControlTemplate:

TestControl

<UserControl x:Class="TestControl">
  <UserControl.Template>
    <ControlTemplate TargetType="local:TreeIndex">
      <Border>
        <Grid>
          ...
          <ContentPresenter Content="{TemplateBinding Content}" />
        </Grid>
      </Border>
    </ControlTemplate>
  </UserControl.Template>
</UserControl>

DataTemplate

<DataTemplate DataType="{x:Type local:TestViewModel}">
  <local:TestControl>
    <TextBlock Text="{Binding Path=Message, Mode=OneWay}"/>
  </local:TestControl>
</DataTemplate>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...