ListBoxItem выдает ошибку System.Windows.Data: ошибка привязки 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>

Это приведет к появлению следующей строки в окне вывода 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='');

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

Обновление:

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


person BennoDual    schedule 18.10.2010    source источник
comment
Вам вообще нужен этот стиль? почему вы не можете установить выравнивание на стековой панели / текстовом блоке на табличке данных?   -  person John Gardner    schedule 18.10.2010


Ответы (5)


Самый простой способ решить эту проблему - убедиться, что в вашем 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, и изменение связанного источника для этих шаблонов вызвало бы эти предупреждения.

person Etienne    schedule 15.10.2011

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

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, а вместо этого создать класс, содержащий нужные мне данные (заголовок и элементы). Просто передаю свою ситуацию на случай, если есть параллели с вашей.

person bsegraves    schedule 01.11.2010

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

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

Ссылка: Как подавить System.Windows.Data Предупреждение об ошибке

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

person akjoshi    schedule 30.11.2011
comment
написал об этом здесь - weblogs.asp.net/akjoshi/archive/2011/11/30/ - person akjoshi; 01.12.2011
comment
Это плохая идея. Во-первых, ошибки отображаются только в Visual Studio, поэтому это не ошибка пользователя. Во-вторых, вы СКРЫВАЕТЕ ОШИБКУ. У ошибки есть причина, и ее сокрытие (вместе со всеми ее братьями и сестрами), скорее всего, в конечном итоге ухудшит ваше положение. Исправьте ошибку, не скрывайте! - person Peter Drier; 20.12.2011
comment
Я как бы не согласен. Мы взрослые, которые могут помнить, что мы отключили ошибку на некоторое время, и возвращаться к проблемам, когда это становится более важным для нужд нашего приложения. Вы можете думать об ошибке как о чрезмерном предупреждении о том, что в противном случае было бы грубой - но полезной - разновидностью ковариации WPF: вы можете привязать строку ListView к менее производному объекту, и приятно иметь те поля, которые среда выполнения объекта не бывает, оставьте поле пустым. - person Glenn Slayden; 02.11.2013
comment
Кажется неправильным скрывать ошибку просто из-за одного сценария, который ее выплевывает. - person Epirocks; 18.08.2017

Для меня виновником был TreeView, а не ListView. Я добавил глобальный стиль в свой App.xaml, как это было предложено @bsegraves:

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

Мне также пришлось добавить в свой TreeView следующее:

<TreeView.ItemContainerStyle>
    <Style
        BasedOn="{StaticResource {x:Type TreeViewItem}}"
        TargetType="{x:Type TreeViewItem}">         
    </Style>
</TreeView.ItemContainerStyle>

По какой-то причине атрибут BasedOn оказался недостающим. (Я пробовал подход @Etienne, но он не сработал.)

person NielW    schedule 03.02.2021

Эти HorizontalContentAlignment и VerticalContentAlignment проблемы вызваны тем, что контейнер не определяет свои HorizontalAlignment и VerticalAlignment соответственно.

Поэтому вместо создания общего стиля (ов) для ListBoxItem, TreeViewItem или того хуже с исчерпывающей установкой этих свойств напрямую, я сделал общий стиль для ItemsControl в моем App.xaml, который решил все, что вызывает эту проблему, например:

<Style TargetType="{x:Type ItemsControl}">
        <Setter Property="HorizontalAlignment" Value="Left" />
        <Setter Property="VerticalAlignment" Value="Top" />
</Style>
person 0tombo0    schedule 24.04.2021