Cross-ListBox在嵌套ListBox WP7应用程序中选择

时间:2011-05-24 14:29:32

标签: windows-phone-7 listbox nested dependency-properties multi-select

在Windows Phone 7应用程序中嵌套ListBox的已知“问题”是,对于每个父类别,它们各自的子ListBox保留其自己的SelectedItems列表。好吧,我有一种情况,这是预期的行为,但我在捕获父和子列表框选定列表时遇到问题。

当前功能:  1.列出项目  2.列出项目  3.加载父和子ListBox数据正在运行  4.多选择父列表框项目可以完美地工作  5.多选Child ListBox项目有效,但无法访问  6.多个不同父项的子ListBox项目在UI中工作,但滚动大型列表集时选择丢失且无法访问  7. lstCategory可以直接访问,但是lstSubCategory不能直接访问(可能,我只是不知道如何)  8.我绑定了一个ViewModel,它有一个复杂的对象,它将两个ListBoxes表示为两个List对象。

预期功能: 我希望能够选择Category(父)和SubCategory(子)ListBox项,如下所示; (X)表示选择:

  • 面包(X)
    • 面包(X)
    • 羊角面包
    • Buscuit(X)
    • 甜甜圈
  • 水果
    • Pinaple(X)
    • 草莓
  • 饮品(X)
    • 牛奶(X)
    • 果汁(X)
    • 纯碱
  • 零食(X)
    • 芯片
    • 弗里斯
    • Trail Mix

即使这是一个很长的列表,我也想保留这些选择。所以,我想要捕捉和使用的是:

  • 面包(X)
  • 面包(X)
  • Buscuit(X)
  • Pinaple(X)
  • 饮品(X)
  • 牛奶(X)
  • 果汁(X)
  • 零食(X)

由于我在每个项目的对象中都有一个CategoryID,因此我可以删除捕获时的层次信息。

对于breivity,这是代码的本质:

        <ListBox 
            x:Name="lstCategory"
            SelectionMode="Multiple" 
            ItemsSource="{Binding Categories}" 
            FontSize="32" 
            Margin="0,0,0,67">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <StackPanel Orientation="Vertical">
                            <TextBlock Text="{Binding CategoryName}"
                                        FontSize="36"
                                        TextWrapping="Wrap"
                                        Margin="20,0,0,0"
                                        VerticalAlignment="Top"/>
                            <StackPanel  Orientation="Vertical" Margin="60,0,0,0">
                                <ListBox
                                    x:Name="lstSubCategory"
                                    SelectionMode="Multiple" 
                                    ItemsSource="{Binding SubCategories}">
                                    <ListBox.ItemTemplate>
                                        <DataTemplate>
                                            <TextBlock Text="{Binding SubCategoryName}"
                                                       FontSize="28"
                                                       TextWrapping="Wrap"
                                                       VerticalAlignment="Top"/>
                                        </DataTemplate>
                                    </ListBox.ItemTemplate>
                                </ListBox>
                            </StackPanel>
                        </StackPanel>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

ViewModel:

    public List<Category> Categories { get; set; }

    public PostCategorySelectVM()
    {
        Categories = new List<Category>()
        {
            new Category() 
            { 
                CategoryID = 0, 
                CategoryName = "Bread",
                SubCategories = new List<SubCategory>()
                {
                    new SubCategory() {
                        CategoryID = 001,
                        SubCategoryName = "Loaf"
                    },
                    new SubCategory() {
                        CategoryID = 002,
                        SubCategoryName = "Croissant"
                    }
                    // ...
                }
                // ...
            }
            // ...
        }
    }

类别类:

public class Category
{
    public int CategoryID { get; set; }
    public string CategoryName { get; set; }
    public List<SubCategory> SubCategories { get; set; }
}

SubCategory类:

public class SubCategory
{
    public int CategoryID { get; set; }
    public string SubCategoryName { get; set; }
}

保存按钮单击事件:

    private void btnSave_Click(object sender, RoutedEventArgs e)
    {
        foreach (Category item in lstCategory.SelectedItems)
        {
            catList.Add(item);
        }

        foreach (Category cat in catList)
        {
            scatList = cat.SubCategories;
            foreach (SubCategory scat in scatList)
            {
                // How do I select the "Selected" SubCategories?
                // How do I select the lstSubCategory control?
            }
        }
    }

最后的笔记:

  • 我唯一的领导与relancy属性有关,但我见过的唯一例子需要在WP7上没有的FrameworkPresentation.dll。
  • 嵌套的ListBox具有预期的UI功能(滚动时删除交叉选择的大型列表除外)
  • 当同一屏幕上显示Category和SubCategory时,用户体验感觉最佳。
  • 将UI功能视为目录搜索引擎。您可能希望以不同的组合选择一般类别和/或子类别,但父级不应该要求子级,子级不应该要求父级,但子级和父级都可以存在(为了特殊性)。

1 个答案:

答案 0 :(得分:1)

您可以在数据模板中使用复选框而不是文本框,然后将复选框的IsChecked属性绑定到Category / Subcategory类中的IsSelected属性:

    <ListBox x:Name="lstCategory"
        ItemsSource="{Binding Categories}" 
        FontSize="32" 
        Margin="0,0,0,67">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Vertical">
                    <CheckBox Content="{Binding CategoryName}"
                                FontSize="36"
                                IsChecked="{Binding IsSelected,Mode=TwoWay}"
                                Margin="20,0,0,0"
                                VerticalAlignment="Top"/>
                    <ListBox ItemsSource="{Binding SubCategories}" Margin="60,0,0,0">
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <CheckBox Content="{Binding SubCategoryName}"
                                            FontSize="28"
                                            IsChecked="{Binding IsSelected,Mode=TwoWay}"
                                            VerticalAlignment="Top"/>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

您还应该让您的类别/子类别类实现INotifyPropertyChanged,以便在设置IsSelected时正确触发通知。

假设你的保存看起来像(这不是'确切的!)

private void btnSave_Click(object sender, RoutedEventArgs e)
{
    catList.Clear();
    catList.AddRange( lstCategory.Items.OfType<Category>().Where(x=>x.IsSelected));

    scatList.Clear();
    foreach (Category cat in catList)
    {
        scatList.AddRange(cat.SubCategories.Where(x=>x.IsSelected));
    }
}