Cannot find source for binding

烈酒焚心 提交于 2019-11-30 00:26:08

问题


My application would throw this error message when I added a new tab and then deleted it:

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')

It didn't complain if I added a new tab, switched to another tab, switched back, and then deleted it. Seemed like something was "updated" during the switches, but I couldn't figure out what and how to fix them.

This is my xaml file:

<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>

And this is my codes for adding/deleting tabs:

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;
                }
            }
        }

Let me know if you need to see more codes. Thanks in advance.


回答1:


As Zarat mentioned the default style for TabItem in Windows 8 has triggers that fire after the remove and then look for the now missing TabControl. I consider that a bug because adding and removing TabItems is a really common scenario isn't it?

I found as a workaround, that it is possible to remove the template of the 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);
}

That looks ok in my scenario, because I will not use the TabItem any more.

I also tried clearing the triggers collection of the template or clearing the conditons collection of its triggers, but it is not allowed to do that (errors).
Also there does not seem to be a way tot disable the triggers.




回答2:


It's not a bug, just some noise coming from the WPF binding engine when it updates bindings and notices something went missing. It's unfortunate that it can't be silenced. Maybe its worth reporting on Connect or the MSDN forums, but don't expect any quick reactions.

The message you noticed comes from aero2.normalcolor.xaml - the default styles for Windows 8. If you got VS 2012 SP 2 installed in the default location you can find them here: C:\Program Files (x86)\Microsoft Visual Studio 11.0\Blend\SystemThemes\Wpf

In this file are a few MultiDataTriggers with conditions to check the TabStripPlacement over a RelativeSource, looking for the parent TabControl. So when you remove a TabItem from the TabControl it is possible that the binding engine tries to update the binding and finds the parent missing, logging a warning. Thats entirely ok since the TabItem was removed and you no longer care about the styles (if you were to add it again the bindings would be reevaluated and everything would be fine, too).

Now I don't know why they retrieve the TabStripPlacement over a RelativeSource for Windows 8, since the TabItem itself seems to carry a copy of its parents TabStripPlacement. All the other default styles use that local copy of TabStripPlacement for their bindings. So if you feel adventurous you may want to copy the style into your own resource dictionary and use a "fixed" version during debugging to reduce noise ...



来源:https://stackoverflow.com/questions/14419248/cannot-find-source-for-binding

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!