ItemsControl 中的 RelativeSource 绑定不起作用

RelativeSource binding in ItemsControl doesn't work

我遇到了以下绑定问题。我在 MainWindow.xaml.cs 中有以下 class 声明:

    public List<MyArrayClass> MyArrayData { get; set; }
    public class MyArrayClass
    {
        public ObservableCollection<int> MyArrayInt { get; set; }
        public ObservableCollection<Thickness> MyArrayBorder { get; set; }
    }

我创建对象如下:

        MyArrayClass sample3 = new MyArrayClass
        {
            MyArrayInt = new ObservableCollection<int> { 0, 1, 2, 3 },
            MyArrayBorder = new ObservableCollection<Thickness> { new Thickness(0,0,0,2), new Thickness(0, 0, 0, 2), new Thickness(0, 0, 0, 2), new Thickness(0, 0, 0, 2) }
        };

        MyArrayData = new List<MyArrayClass>();
        MyArrayData.Add(sample3);

话虽如此,我的 objective 是使用 ItemsControl 对象将 MyArrayInt 的内容显示到一组 TextBlock 中(我试图了解它是如何工作的)。特别是,我希望能够通过绑定定义每个 TextBlock 的边框。我的 XAML 看起来像:

<ItemsControl Name="List" ItemsSource="{Binding MyArrayData}" Grid.Row="1" Grid.Column="1">
        <!-- List<> -->
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <ItemsControl Name="MyArrayInt" ItemsSource="{Binding MyArrayInt}">
                    <!-- Array of int-->
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel Orientation="Horizontal"/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <Border BorderBrush="Red" BorderThickness="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}, AncestorLevel=2}, Path=MyArrayBorder}">
                                <TextBlock Text="{Binding Path=.}" Background="Azure" Margin="2,0,0,0"/>
                            </Border>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

结果如我所料显示了 MyArrayInt,但我在 BorderThickness 绑定上收到以下错误:

System.Windows.Data 错误:40:BindingExpression 路径错误:'MyArrayBorder' 属性 未在 'object' ''ItemsControl' 上找到(名称='List' )'。 BindingExpression:Path=MyArrayBorder; DataItem='ItemsControl' (名称='List');目标元素是 'Border' (Name='');目标 属性 是 'BorderThickness'(类型 'Thickness')

按照我的阅读方式,RelativeSource 绑定似乎是正确的:ItemsControl 对象的名称是 'List',它是绑定到 MyArrayData 的对象。那么为什么它找不到 MyArrayBorder?

欢迎提出任何建议!

你的绑定有误。 您可以使用 ListBox 或 ListItem 而不是 ItemsControl 然后设置 BorderThickness="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}, AncestorLevel=2}, Path=SelectedItem.MyArrayBorder}"

与其在 MyArrayClass 中拥有两个集合属性,不如创建一个自定义类型并将它们合并为一个:

public class MyArrayClass
{
    public ObservableCollection<MyType> MyArray { get; set; }
}
...
public class MyType
{
    public int MyArrayInt { get; set; }
    public Thickness MyArrayBorder { get; set; }
}

然后您可以轻松绑定到新类型中的每个属性:

<ItemsControl Name="MyArrayInt" ItemsSource="{Binding MyArray}">
    <!-- Array of int-->
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Border BorderBrush="Red" BorderThickness="{Binding MyArrayBorder}">
                <TextBlock Text="{Binding MyArrayInt}" Background="Azure" Margin="2,0,0,0"/>
            </Border>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

鉴于您当前的设置,您需要使用转换器才能从 MyArrayClassMyArrayBorder 集合中获取特定项目。

您确实可以轻松绑定到 MyArrayBorder 属性 本身:

BorderThickness="{Binding Path=MyArrayBorder[0], 
    RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}"

...但是您不能使用纯 XAML.

绑定到动态索引处的项目(在上面的截图中用 0 替换)