【问题标题】:Cannot bind to ListBox child of ListBox无法绑定到 ListBox 的 ListBox 子项
【发布时间】:2016-04-21 13:51:57
【问题描述】:

我正在绑定到一个 ListBox,并且在 ListBox 中,还有另一个 ListBox。

我的模型看起来像

public interface ICriteriaDetail
{
    string Title { get; }
    int NumberOfEvents { get; }
    ICriteriaDetail ChildCriteria { get; }
}

所以,我对孩子使用递归方法(不是列表)。

当我绑定到我的 ListView 时,我会得到一个列表中的项目,一个在另一个之下。

问题是,子项根本没有显示!

虚拟数据

  public static IEnumerable<ICriteriaDetail> GetCriteriaList()
    {
        var list = new List<CompoundCriteria.Ui.Model.Interfaces.ICriteriaDetail>();
        list.Add(GetCriteriaDetail("My Title", 5, false));
        list.Add(GetCriteriaDetail("Other", 3, false));
        list.Add(GetCriteriaDetail("Biggy", 8, true));

        var child = new CompoundCriteria.Ui.Model.CriteriaDetail.CriteriaDetail("childAgain", 43, null);
        var child2 = new CompoundCriteria.Ui.Model.CriteriaDetail.CriteriaDetail("childAgainAgain", 13, child);

        list.Add(new CompoundCriteria.Ui.Model.CriteriaDetail.CriteriaDetail("Really big", 86, new CompoundCriteria.Ui.Model.CriteriaDetail.CriteriaDetail("smaller", 15, child2)));

        return list;
    }

    private static ICriteriaDetail GetCriteriaDetail(string title, int events, bool hasChild)
    {
        if (!hasChild)
            return new CompoundCriteria.Ui.Model.CriteriaDetail.CriteriaDetail(title, events, null);

        var child = new CompoundCriteria.Ui.Model.CriteriaDetail.CriteriaDetail("child" + title, 13 + events, null);
        return new CompoundCriteria.Ui.Model.CriteriaDetail.CriteriaDetail(title, events, child);
    }

视图模型

    public MainWindowViewModel()
    {
        this.Criterias = DatasourceMockup.GetCriteriaList();
    }

    private IEnumerable<ICriteriaDetail> _criterias;
    public IEnumerable<ICriteriaDetail> Criterias
    {
        get { return _criterias; }
        set { _criterias = value; }
    }

XAML 中的 ListBox

 <ListBox ItemsSource="{Binding Criterias}" >
                    <ListBox.Resources>
                         <ControlTemplate x:Key="con">
                            <StackPanel Orientation="Horizontal">
                            <StackPanel Margin="15">
                                <TextBlock Text="{Binding Title}" />
                                <TextBlock Text="Events: ">
                                <Run Text="{Binding NumberOfEvents}" />
                                </TextBlock>
                             </StackPanel>
                             <ListBox ItemsSource="{Binding ChildCriteria} Visibility="{Binding ChildCriteria, Converter={StaticResource HideIfNull}}">">
                                    <ListBox.Resources>
                                        <DataTemplate DataType="{x:Type cDetail:CriteriaDetail}">
                                                <TextBlock Text="{Binding Title}" />
                                        </DataTemplate>
                                    </ListBox.Resources>
                                </ListBox>
                            </StackPanel>
                        </ControlTemplate>

                        <HierarchicalDataTemplate DataType="{x:Type cDetail:CriteriaDetail}">
                                <Control Template="{StaticResource con}" />
                        </HierarchicalDataTemplate>
                    </ListBox.Resources>
                </ListBox>

阅读TreeView, HierarchicalDataTemplate and recursive Data 后,HierarchicalDataTemplate 似乎就足够了(也不需要 DataTemplate)但是,我不知道为什么我没有看到我期望的结果(即使孩子们没有在想要的地方,我还是希望能看到他们)

编辑

我刚刚添加了一个转换器,如果绑定数据为空,它会隐藏 ListBox(ControlTemplate 中的那个)。我只有 3 个中的 1 个(这是正确的)的大纲(一个空的 ListBox),但它不绑定任何内容(标题)。输出窗口显示没有任何用处...

请注意,儿童人数没有限制。在上面的例子中,有一个父子关系,但它可能是父子子子等

【问题讨论】:

    标签: c# wpf xaml listbox


    【解决方案1】:

    1) 很难理解你的目的,为什么 ListBox,如果你的模型中有ChildCriteria,而不是IEnumerable&lt;ICriteriaDetail&gt;

    2) 你也有绑定错误,我把 xaml 改成了

    <ListBox ItemsSource="{Binding Criterias}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <StackPanel Margin="15">
                                <TextBlock Text="{Binding Title}" />
                                <TextBlock Text="Events: ">
                                    <Run Text="{Binding NumberOfEvents}" />
                                </TextBlock>
                    </StackPanel>
                    <TextBox Text="{Binding Path=DataContext.ChildCriteria.Title, 
                                            RelativeSource={RelativeSource Mode=FindAncestor, 
                                                            AncestorType={x:Type ListBoxItem}, 
                                                            AncestorLevel=1}}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    

    得到了

    编辑1: 1)我将数据模型更改为

    public class CriteriaDetail : ICriteriaDetail
    {
        public CriteriaDetail(string title, int numberOfEvents, IEnumerable<ICriteriaDetail> childCriteria)
        {
            Title = title;
            NumberOfEvents = numberOfEvents;
            ChildCriteria = childCriteria;
        }
    
        public string Title { get; set; }
        public int NumberOfEvents { get; set; }
        public IEnumerable<ICriteriaDetail> ChildCriteria { get; set; }
    }
    

    2) 将 xaml 更改为

    <TreeView ItemsSource="{Binding Criterias}">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding ChildCriteria}">
                    <TextBlock Foreground="Red" Text="{Binding Title}"/>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
    </TreeView>
    

    3) 将 GetCriteriaDetail 更改为

        private static ICriteriaDetail GetCriteriaDetail(string title, int events, bool hasChild)
        {
            if (!hasChild)
                return new CriteriaDetail(title, events, null);
    
            var child3 = new CriteriaDetail("child3" + title, 13 + events, null);
            var child2 = new CriteriaDetail("child2" + title, 13 + events, new ICriteriaDetail[] { child3 });
            var child1 = new CriteriaDetail("child1" + title, 13 + events, new ICriteriaDetail[] { child2 });
    
    
            return new CriteriaDetail(title, events, new ICriteriaDetail[] {child1});
        }
    

    并得到了这个。我觉得它看起来更像你想要的

    【讨论】:

    • 遗憾的是,这只有在有 1 个孩子的情况下才有用。每个父母只会有 1 个孩子,因此不使用 IEnumerable,并且可以选择 recusrvive 属性。我已经更新了我帖子的 Dummy 数据以显示更好的示例
    • 虽然我越想越觉得你可能是对的,以这种方式使用递归可能不太适合模板模型。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-17
    • 1970-01-01
    • 1970-01-01
    • 2012-06-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多