找不到绑定源

use*_*343 22 c# wpf binding

当我添加新选项卡然后将其删除时,我的应用程序将抛出此错误消息:

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')
Run Code Online (Sandbox Code Playgroud)

如果我添加了一个新选项卡,切换到另一个选项卡,切换回来然后删除它,它没有抱怨.看起来像是在切换过程中"更新"的东西,但我无法弄清楚是什么以及如何解决它们.

这是我的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>
Run Code Online (Sandbox Code Playgroud)

这是我添加/删除标签的代码:

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;
                }
            }
        }
Run Code Online (Sandbox Code Playgroud)

如果您需要查看更多代码,请与我们联系.提前致谢.

Ger*_*ard 15

正如Zarat所提到的,Windows 8中TabItem的默认样式具有在删除后触发的触发器,然后查找现在缺少的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);
}
Run Code Online (Sandbox Code Playgroud)

在我的场景中看起来没问题,因为我不会再使用TabItem了.

我还尝试清除模板的触发器集合或清除其触发器的条件集合,但不允许这样做(错误).
似乎也没有办法禁用触发器.

  • 谢谢!这件事情让我感到很快乐。在删除选项卡之前设置 `Template = null` 后不再有警告。 (2认同)
  • 不幸的是我的标签项使用Caliburn数据绑定到viewModel :( (2认同)

Zar*_*rat 7

它不是一个bug,只是来自WPF绑定引擎的一些噪音,当它更新绑定并注意到某些内容丢失时.不幸的是它无法沉默.也许它值得报道Connect或MSDN论坛,但不要指望任何快速反应.

您注意到的消息来自aero2.normalcolor.xaml - Windows 8的默认样式.如果您在默认位置安装了VS 2012 SP 2,可以在此处找到它们:C:\ Program Files(x86)\ Microsoft Visual Studio 11.0 \混合\ SystemThemes\WPF

在这个文件中有一些MultiDataTriggers,它们具有通过RelativeSource检查TabStripPlacement的条件,寻找父TabControl.因此,当您从TabControl中删除TabItem时,绑定引擎可能会尝试更新绑定并找到父项缺失,并记录警告.这完全没问题,因为TabItem被移除了,你不再关心样式(如果你再次添加它,绑定将被重新评估,一切都会很好).

现在我不知道为什么他们为Windows 8的RelativeSource检索TabStripPlacement,因为TabItem本身似乎带有其父项TabStripPlacement的副本.所有其他默认样式都使用TabStripPlacement的本地副本进行绑定.因此,如果您喜欢冒险,您可能希望将样式复制到您自己的资源字典中,并在调试期间使用"固定"版本以减少噪音......