ListBoxItem создает ошибку "Ошибка System.Windows.Data Error: 4"

Я создал файл ListBox:

<ListBox x:Name="RecentItemsListBox" Grid.Row="1" BorderThickness="0" Margin="2,0,0,0" SelectionChanged="RecentItemsListBox_SelectionChanged">
  <ListBox.Resources>
      <Style TargetType="{x:Type ListBoxItem}"
             BasedOn="{StaticResource {x:Type ListBoxItem}}">
          <Style.Triggers>
              <!--This trigger is needed, because RelativeSource binding can only succeeds if the current ListBoxItem is already connected to its visual parent-->
              <Trigger Property="IsVisible" Value="True">
                  <Setter Property="HorizontalContentAlignment"
                          Value="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
                  <Setter Property="VerticalContentAlignment"
                          Value="{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
              </Trigger>
          </Style.Triggers>
      </Style>
  </ListBox.Resources>
  <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal" Margin="0,2,0,0">
                <TextBlock Text="{Binding Number}" />
                <StackPanel Orientation="Vertical" Margin="7,0,0,0">
                    <TextBlock Text="{Binding File}" />
                    <TextBlock Text="{Binding Dir}" Foreground="DarkGray" />
                </StackPanel>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Это приведет к тому, что во время выполнения выйдет строка в OutputWindow из VisualStudio:

System.Windows.Data Error: 4 : 
 Cannot find source for binding with reference 'RelativeSource FindAncestor, 
 AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''. 
 BindingExpression:Path=HorizontalContentAlignment; DataItem=null; 
 target element is 'ListBoxItem' (Name='');

Может кто-нибудь дать мне подсказку, как я могу это решить?

Обновление

Я добавил свойства в стиль, чтобы попытаться устранить предупреждение/ошибку.

Ответ 1

Самый простой способ решить этот вопрос - убедиться, что Listbox имеет ItemContainerStyle. См. Следующий пример:

<ListBox x:Name="RecentItemsListBox" Grid.Row="1" BorderThickness="0" Margin="2,0,0,0" SelectionChanged="RecentItemsListBox_SelectionChanged">
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <Setter Property="HorizontalContentAlignment" Value="Left"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
        </Style>
    </ListBox.ItemContainerStyle>

...

</ListBox>

Случается, что ваши объекты создаются, и по умолчанию они ищут родительское свойство, которое не определено. Явное определение проблемы решит эту проблему.

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

Ответ 2

Ответ на этот вопрос разрешил мне эту проблему:

ListBox с сеткой как ItemsPanelTemplate создает странные ошибки привязки

Определение стиля верхнего уровня (в моем App.xaml), нацеленного на проблему типа "исправлено" для меня. Вот стиль, который должен сработать для вас:

<Style TargetType="{x:Type ListBoxItem}">
     <Setter Property="HorizontalContentAlignment" Value="Left" />
     <Setter Property="VerticalContentAlignment" Value="Top" />
</Style>

В моем случае я создавал некоторые TreeViewItems, а затем привязывал свой TreeView к созданным элементам. Ошибка привязки произошла, потому что привязка TreeViewItem была разрешена до того, как они были добавлены в TreeView. Правильное решение состояло в том, чтобы не создавать TreeViewItem, а вместо этого создавать класс, содержащий нужные мне данные (Header и Items). Просто передайте мою ситуацию, если есть параллели с вашими собственными.

Ответ 3

Другим обходным решением, которое работало на меня, было подавление этих ошибок (на самом деле, более целесообразно называть их предупреждениями) путем установки уровня переключения источника привязки данных как критического в конструкторе класса или окна верхнего уровня -

#if DEBUG     
    System.Diagnostics.PresentationTraceSources.DataBindingSource.Switch.Level =
        System.Diagnostics.SourceLevels.Critical;
#endif

Ref.: Как подавить сообщение об ошибке System.Windows.Data Error

Обновление: это не лучшее решение, но для вредоносных программ это выглядит хорошо для меня.