Подтвердить что ты не робот

Не удается найти источник для привязки

Мое приложение бросит это сообщение об ошибке, когда я добавлю новую вкладку, а затем удалю ее:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.TabControl', AncestorLevel='1''. BindingExpression:Path=TabStripPlacement; DataItem=null; target element is 'TabItem' (Name=''); target property is 'NoTarget' (type 'Object')

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

Это мой файл xaml:

<Window x:Class="MyHomework__MVVM_.MyHomeworkView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Title="My Homework" Height="450" Width="800" ResizeMode="CanMinimize">
    <Grid Margin="0,0,10,10">
        <TabControl HorizontalAlignment="Left" Height="330" VerticalAlignment="Top" Width="764" Margin="10,10,0,0" ItemsSource="{Binding AllTabs}" SelectedItem="{Binding SelectedTab}">
            <TabControl.ItemContainerStyle>
                <Style TargetType="TabItem">
                    <Setter Property="Header" Value="{Binding Header}"/>
                    <Setter Property="ContentTemplate">
                        <Setter.Value>
                            <DataTemplate>
                                <Grid>
                                    <TextBox Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" FontSize="16" AcceptsReturn="True" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" TextChanged="OnTextChanged">
                                    </TextBox>
                                </Grid>
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                    <Setter Property="FontSize" Value="20"/>
                </Style>
            </TabControl.ItemContainerStyle>
        </TabControl>
        <Button Content="Add Course" HorizontalAlignment="Left" VerticalAlignment="Top" Width="105" Margin="10,351,0,0" Height="50" Command="{Binding AddCourseCommand}"/>
        <Button Content="Drop Course" HorizontalAlignment="Left" VerticalAlignment="Top" Width="76" Margin="126,379,0,0" Height="22" Command="{Binding DropCourseCommand, UpdateSourceTrigger=PropertyChanged}"/>
        <Button Content="Save HW" HorizontalAlignment="Left" VerticalAlignment="Top" Width="105" Margin="669,351,0,0" Height="50" Command="{Binding SaveHomeworkCommand, UpdateSourceTrigger=PropertyChanged}"/>
    </Grid>
</Window>

И это мои коды для добавления/удаления вкладок:

public void AddNewTab()
        {
            NewCourseName ncn = new NewCourseName();
            ncn.Owner = mainWindow;
            ncn.ShowDialog();
            if (ncn.courseName != null)
            {
                MyHomeworkModel newTab = new MyHomeworkModel();
                newTab.Header = ncn.courseName;
                newTab.Text = "";
                AllTabs.Add(newTab);
                SelectedTab = newTab;
            }
        }

public void RemoveTab()
        {
            DropCourseConfirmation dcc = new DropCourseConfirmation();
            dcc.Owner = mainWindow;
            dcc.ShowDialog();
            if (dcc.drop == true)
            {
                int index = AllTabs.IndexOf(SelectedTab);
                AllTabs.Remove(SelectedTab);

                if (AllTabs.Count > 0)
                {
                    if (index == 0)
                    {
                        SelectedTab = AllTabs[0];
                    }
                    else
                    {
                        SelectedTab = AllTabs[--index];
                    }
                }
                else
                {
                    SelectedTab = null;
                }
            }
        }

Сообщите мне, если вам нужно увидеть больше кодов. Спасибо заранее.

4b9b3361

Ответ 1

Как Zarat упоминает, что стиль по умолчанию для TabItem в Windows 8 имеет триггеры, которые запускают после удаления, а затем ищут отсутствующий TabControl. Я считаю, что ошибка, потому что добавление и удаление TabItems - действительно распространенный сценарий, не так ли?

Я нашел в качестве обходного пути, что можно удалить шаблон TabItem:

foreach (var item in TabControl.Items)
{
    var tabitem = item as TabItem;
    // if this is the item to remove
    tabitem.Template = null;
    TabControl.Items.Remove(item);
}

В моем сценарии это выглядит нормально, потому что я больше не буду использовать TabItem.

Я также попытался очистить сборку триггеров шаблона или очистить коллекцию триггеров conditons, но это не позволяет делать это (ошибки).
Также не существует способа отключить триггеры.

Ответ 2

Это не ошибка, только некоторый шум, исходящий из механизма привязки WPF, когда он обновляет привязки и уведомления, что-то пропало. Это печально, что его нельзя заставить замолчать. Возможно, его стоит сообщать о Connect или форумах MSDN, но не ожидайте быстрых реакций.

Сообщение, которое вы заметили, связано с aero2.normalcolor.xaml - стилями по умолчанию для Windows 8. Если вы установили VS 2012 SP 2 в папку по умолчанию, вы можете найти их здесь: C:\Program Files (x86)\Microsoft Visual Studio 11.0\Blend\SystemThemes\Wpf

В этом файле несколько MultiDataTriggers с условиями для проверки TabStripPlacement над RelativeSource, для поиска родительского TabControl. Поэтому, когда вы удаляете TabItem из TabControl, возможно, что механизм привязки пытается обновить привязку и обнаруживает, что родительский элемент отсутствует, регистрируя предупреждение. Это полностью нормально, так как TabItem был удален, и вы больше не заботитесь о стилях (если вы должны добавить его снова, привязки будут переоценены, и все будет хорошо).

Теперь я не знаю, почему они извлекают TabStripPlacement через RelativeSource для Windows 8, так как сам TabItem, похоже, несут копию своих родителей TabStripPlacement. Все остальные стили по умолчанию используют эту локальную копию TabStripPlacement для привязки. Поэтому, если вы чувствуете себя странно, вы можете скопировать стиль в свой собственный словарь ресурсов и использовать "исправленную" версию во время отладки, чтобы уменьшить шум...