模糊的绑定行为

时间:2017-11-27 11:21:31

标签: c# wpf data-binding

我有一个自定义TabItem:

public class FooTabItem : TabItem
{
    public static readonly DependencyProperty ButtonsProperty =
        DependencyProperty.Register("Buttons", typeof(List<Button>), typeof(FooTabItem), new PropertyMetadata(new List<Button>()));


    public List<Button> Buttons
    {
        get => (List<Button>) GetValue(ButtonsProperty);
        set => SetValue(ButtonsProperty, value);
    }
}

以及以下使用可能会查看:

[...]
    <Grid Grid.Row="0">
[...]
        <Label Grid.Column="0" Content="{Binding ElementName=TabControl, Path=SelectedItem.Header}" />
        <ItemsControl Grid.Column="3" HorizontalAlignment="Right" ItemsSource="{Binding ElementName=TabControl, Path=SelectedItem.Buttons}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel Orientation="Horizontal" FlowDirection="RightToLeft" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
    </Grid>
    <TabControl Grid.Row="1" x:Name="TabControl" TabStripPlacement="Left">
        <TabControl.Items>
            <local:FooTabItem x:Name="First" Header="abc">
                <local:FooTabItem.Buttons>
                    <Button Content="a23"/>
                    <Button Content="a56"/>
                    <Button Content="a89"/>
                </local:FooTabItem.Buttons>
            </local:FooTabItem>
            <local:FooTabItem x:Name="Second" Header="def">
                <local:FooTabItem.Buttons>
                    <Button Content="rfv"/>
                    <Button Content="tgb"/>
                </local:FooTabItem.Buttons>
            </local:FooTabItem>
        </TabControl.Items>
    </TabControl>
</Grid>

enter image description here

根据所选择的标签,我预计会分别有三个按钮,但我得到全部五个按钮。 为什么以及如何解决这个问题?

2 个答案:

答案 0 :(得分:4)

该行为是由您将对象的默认值设置为new List<Button>()引起的。这意味着除非明确设置,否则List<Button>属性中的所有对象都将具有相同的Buttons实例。

用于Buttons属性的语法意味着您要添加到现有列表而不创建新列表。

你可以尝试创建一个类:

class ListOfButtons : List<Button>
{
}

没有为属性设置默认值,而在XAML中创建ListOfButtons的新实例:

 <local:FooTabItem.Buttons>
     <local:ListOfButtons>
         <Button x:Name="a23"/>
         <Button x:Name="a56"/>
         <Button x:Name="a89"/>
     </local:ListOfButtons>
 </local:FooTabItem.Buttons>

答案 1 :(得分:4)

在控件的构造函数中初始化依赖项属性:

public class FooTabItem : TabItem
{
    public FooTabItem()
    {
        Buttons = new List<Button>();
    }

    public static readonly DependencyProperty ButtonsProperty =
        DependencyProperty.Register("Buttons", typeof(List<Button>), typeof(FooTabItem));

    public List<Button> Buttons
    {
        get { return (List<Button>)GetValue(ButtonsProperty); }
        set { SetValue(ButtonsProperty, value); }
    }
}

集合类型依赖项属性: https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/collection-type-dependency-properties

  

[...]因此,您必须小心不要将集合属性元数据定义的单一静态集合用作新创建的类型实例的工作默认值。相反,您必须确保将集合值有意地设置为唯一(实例)集合,作为类构造函数逻辑的一部分。