0

当前设置

我有一个代表安装程序文件的自定义类和关于该文件的一些属性,符合以下接口

public interface IInstallerObject
{
    string FileName { get; set; }
    string FileExtension { get; set; }
    string Path { get; set; }
    int Build { get; set; }
    ProductType ProductType { get; set; }
    Architecture ArchType { get; set; }
    bool Configurable { get; set; }
    int AverageInstallTime { get; set; }
    bool IsSelected { get; set; }
}

ViewModel有一个ReadOnlyObservableCollection<IInstallerObject>名为AvailableInstallerObjects.

MyView有一个GroupBox包含ItemsControl绑定到上述属性的 。

    <GroupBox Header="Products">
        <ItemsControl ItemsSource="{Binding Path=AvailableInstallerObjects}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <CheckBox IsChecked="{Binding Path=IsSelected}"
                                  VerticalAlignment="Center" Margin="5"/>
                        <TextBlock Text="{Binding Path=FileName}" Margin="5" />
                    </StackPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </GroupBox>

绑定工作正常,除了它不是用户友好的。显示了 100 多个项目。

在这里需要帮助

我希望能够使用我的IInstallerObjects 集合,但View现在它们具有以下ItemTemplate结构。

    <GroupBox Header="Products">
        <ItemsControl ItemsSource="{Binding Path=AvailableInstallerObjects}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <CheckBox IsChecked="{Binding Path=IsSelected}"
                                  VerticalAlignment="Center" Margin="5"/>
                        <TextBlock Text="{Binding Path=ProductType}" Margin="5" />
                        <ComboBox ItemsSource="{Binding Path=Build}" />
                    </StackPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </GroupBox>

基本上我希望能够按ProductType属性进行分组,显示可用产品的列表,其中表示 .s的ComboBox可用Build属性值。IInstallerObjectProductType

我可以使用LINQinViewModel来提取分组,但我不知道如何绑定到我提取的内容。

我的研究还发现了使用 a 的可能性,CollectionViewSource但我不确定如何将它应用到我当前的设置中。

我提前感谢您的帮助。我愿意学习,所以如果我忽略了一些明显的东西,请引导我查看信息,我很乐意自学。

4

3 回答 3

0

您的问题的描述使我相信您正在寻找某种折叠/扩展/分组/树视图之类的东西。

树视图的 XAML

<Window x:Class="WPFLab12.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:loc="clr-namespace:WPFLab12"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
      <GroupBox Header="Products">
        <TreeView ItemsSource="{Binding Path=ProductTypes}">
            <TreeView.Resources>
                <HierarchicalDataTemplate 
                    DataType="{x:Type loc:ProductType}"
                    ItemsSource="{Binding AvailableInstallerObjects}">
                    <TextBlock Text="{Binding Description}" />
                </HierarchicalDataTemplate>
                <HierarchicalDataTemplate DataType="{x:Type loc:InstallerObject}">
                    <StackPanel Orientation="Horizontal">
                        <CheckBox IsChecked="{Binding Path=IsSelected}" 
                                  VerticalAlignment="Center" Margin="5"/>
                        <TextBlock Text="{Binding Path=FileName}" Margin="5" />
                    </StackPanel>
                </HierarchicalDataTemplate>
            </TreeView.Resources>
        </TreeView>
      </GroupBox>
    </Grid>
</Window>

那有什么作用?好吧,它根据找到的数据类型在树中建立了控制层次结构。第一个HierarchicalDataTemplate处理如何显示每个类的数据,以及它们在层次结构中的关系。第二个HierarchicalDataTemplate处理如何显示每个InstallerObject.

主窗口背后的代码:

public partial class MainWindow : Window
{
    public ReadOnlyObservableCollection<ProductType> ProductTypes
    {
        get { return (ReadOnlyObservableCollection<ProductType>)GetValue(ProductTypesProperty); }
        set { SetValue(ProductTypesProperty, value); }
    }

    // Using a DependencyProperty as the backing store for ProductTypes.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ProductTypesProperty =
        DependencyProperty.Register("ProductTypes", typeof(ReadOnlyObservableCollection<ProductType>), typeof(MainWindow), new UIPropertyMetadata(null));

    public MainWindow()
    {
        this.InitializeComponent();

        this.ProductTypes = new ReadOnlyObservableCollection<ProductType>(
            new ObservableCollection<ProductType>()
            {
                new ProductType() 
                { 
                    Description = "Type A",
                    AvailableInstallerObjects = new ReadOnlyObservableCollection<InstallerObject>(
                        new ObservableCollection<InstallerObject>()
                        {
                            new InstallerObject() { FileName = "A" },
                            new InstallerObject() { FileName = "B" },
                            new InstallerObject() { FileName = "C" },
                        })
                },

                new ProductType() 
                { 
                    Description = "Type B",
                    AvailableInstallerObjects = new ReadOnlyObservableCollection<InstallerObject>(
                        new ObservableCollection<InstallerObject>()
                        {
                            new InstallerObject() { FileName = "A" },
                            new InstallerObject() { FileName = "D" },
                        })
                }
            });

        this.DataContext = this;
    }
}

不过,这完全是作弊 - 通常MainWindow.cs不会用作 DataContext 并拥有所有这些东西。但是对于这个例子,我只是让它列出一个s 并用实例ProductType填充每个ProductType类。InstallerObject

我使用的类,注意我做了一些假设并修改了你的类以更好地适应这个视图模型:

public class InstallerObject
{
    public string FileName { get; set; }
    public string FileExtension { get; set; }
    public string Path { get; set; }
    public int Build { get; set; }
    public bool Configurable { get; set; }
    public int AverageInstallTime { get; set; }
    public bool IsSelected { get; set; }
}

public class ProductType
{
    public string Description { get; set; }
    public ReadOnlyObservableCollection<InstallerObject> AvailableInstallerObjects
    {
        get;
        set; 
    }
    public override string ToString()
    {
        return this.Description;
    }
}

因此,在 MVVM 中,在我看来,您当前的InstallerObject课程更像是模型层之类的东西。您可能会考虑在您的 ViewModel 中将其转换为一组更易于在您的视图中管理的集合类。ViewModel 中的想法是对事物进行建模,类似于它们将如何被查看和交互。将您的平面列表转换InstallerObjects为新的分层数据集合,以便更轻松地绑定到视图。

有关使用和自定义 TreeView 的各种方式的更多信息:http: //www.codeproject.com/Articles/124644/Basic-Understanding-of-Tree-View-in-WPF

于 2012-07-27T22:04:06.513 回答
0

您所要做的就是CollectionViewSource在您的视图中声明 a 并将其绑定到ObservableCollection. 在此对象中,您声明一个或多个GroupDescriptions,它将​​源分成几组。

将此源绑定到列表框,为组描述创建一个模板,您就完成了。

可以在此处找到示例:WPF 示例系列 - 列表框分组、排序、小计和可折叠区域。更多关于 CollectionViewSource 的信息可以在这里找到:WPF 的 CollectionViewSource

于 2012-07-27T20:34:13.457 回答
0

如果 Build 应该是一个集合类型。

所以你的班级应该像这样作为一个例子。

Public Class Customer
 Public Property FirstName as string
Public Property LastName as string
Public Property CustomerOrders as observableCollection(OF Orders)
End Class

这应该会给你预期的结果。主项目展示器中的每个项目将显示绑定到该客户订单的名字姓氏和组合框。我知道这很简单,但这应该可以。

于 2012-07-27T20:28:28.760 回答