【问题标题】:How to bind to a source inside a ListBox different from the ItemsSource already specified如何绑定到与已指定的 ItemsSource 不同的 ListBox 内的源
【发布时间】:2015-05-13 21:36:42
【问题描述】:

我在 HubSection 中有一个 ListBox,其项目绑定到通过后面的代码添加到我的 DefaulViewModel 的类“玩家”。 首先,我简单地将一个 TextBox 绑定到我的类“players”的属性“PlayerName”。 现在我想添加一个 ComboBox,其中包含一些不属于类播放器的项目。

有可能吗?我认为在 ComboBox 中定义 ItemsSource 会覆盖 ListBox 的 ItemsSource,但没有任何显示。

整个页面的DataContext定义如下:

DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"

那么HubSection就是这样的:

<HubSection x:Name="HubSec1">
        <DataTemplate>                    
            <ListBox x:Name="ListBox1" ItemsSource="{Binding players}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                       <StackPanel>
                            <TextBox Text="{Binding Path=PlayerName, Mode=TwoWay}"/>
                            <ComboBox ItemsSource="{Binding Path=ListOfElements}"/>                                                                                                                                                             
                        </StackPanel>
                     </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </DataTemplate>
</HubSection>

如果我以相同的方式定义组合框但在列表框之外,它将正确显示“ListOfElements”的字符串元素。 但是在这个 ListBox 中,ComboBox 是空的。所以我的猜测是,为 ListBox 定义了 ItemsSource,不可能覆盖它。

我试图定义一个 DataTemplate 但没有成功,但这可能是一个很好的解决方案(而且我没有正确进行)

我错过了什么?

编辑: ComboBox 项是一个 ObservableCollection。它不是“玩家”类的一部分。 这是我如何将这些元素添加到 DefaultViewModel

 DefaultViewModel.Add("players", players);
 DefaultViewModel.Add("MyItemsList", ListOfElements);

【问题讨论】:

    标签: c# xaml combobox listbox


    【解决方案1】:

    您可以向上走可视化树并绑定到祖先数据上下文:

    {Binding Path=PathToProperty, RelativeSource={RelativeSource AncestorType={x:Type typeOfAncestor}}}
    

    前:

    {Binding Path=ListOfItems, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}
    

    这应该为您提供列表框具有的数据上下文,因此假设您的 ListOfItems 存在于该数据上下文中。

    或者你可以给你的控件命名,然后通过元素名绑定到它的datacontext:

    {Binding ElementName=mySourceElement,Path=ListOfItems}
    

    【讨论】:

    • 感谢您的帮助。我尝试了“AncestorType”解决方案,但在 IDE 中出现错误:“元素 'RelativeSource' 上的成员未知 'AncestorType'”(法语粗略翻译)。
    • 应该可以,你也可以试试这个方法:{Binding ElementName=ListBox1,Path=ListOfItems}
    • 知道为什么我不能使用 AncestorType 选项。当我输入“RelativeSource={RelativeSource”时,IDE 只建议“Dispatcher”或“Mode”,而不是 AncestorType ...如果我选择 Mode,则有 3 个不同的属性:“none”、“self”、“TemplatedParent”。 ..
    • 如下所述,我猜该方法适用于 WPF,但不适用于 windows phone,对不起,我假设我们在 wpf 中。也许第二种方法会奏效。只需命名您的外部大多数控件,然后按元素名称绑定到它。
    • 这是一个通用应用程序,我正在开发应用程序的“Windows 部分”。但是,我尝试了第二种解决方案,它成功了,感谢您的帮助。
    【解决方案2】:

    在 Windows 应用程序中创建良好的工作绑定可能有点棘手。一种广泛使用的解决方法是使用 Tag 属性。

    <ListBox x:Name="ListBox1" ItemsSource="{Binding players}" Margin="0,184,0,0" Tag="{Binding Path=ListOfElements}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBox Text="{Binding Path=PlayerName, Mode=TwoWay}"/>
                    <TextBox Text="{Binding Path=Tag, ElementName=ListBox1}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    

    绑定到具有特定名称的元素将始终有效。并且ListOfElements 应该在ListBox 的范围内,因此您可以使用Tag 属性作为代理。如果需要绑定多个属性,还可以使用虚拟 XAML 元素:

    <Border Tag="{Binding ...}" Name="dummy1"/>
    

    【讨论】:

    • 不要使用 Tag 属性。没必要,这是一个极坏的习惯。
    • 我的绑定一开始就正确。我不得不从喜欢使用 Tag 属性的开发人员那里修复难以想象的可怕代码,这是 VB 时代遗留下来的旧技巧(你别无选择)。
    • @slugster 我想你会改变模型,对吧?这是可能的,但我不明白为什么我必须更改我的数据结构,如果在 XAML 中完全做到这一点要容易得多。从 XAML 的角度来看,我也不明白它与 VB 有什么关系。 > 我不会将Tag 属性作为内存来从后面的代码中访问它等等;它只会用作值的重定向路由
    • @slugster PS:我从Windows Apps的角度考虑问题。 RelativeSource 不如 WPF 中的那么好。所以@user1336827 的第一个解决方案在那里不起作用。
    • 那么解决方案是什么?问题是否来自我如何组织数据?我的 DefaultViewModel 错了吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-18
    • 2012-02-18
    • 2010-11-24
    • 2023-03-08
    • 1970-01-01
    相关资源
    最近更新 更多