【问题标题】:Silverlight: DataGrid inside ListBox. Binding on DataGrid Column to a parent listbox's ItemsSource property. SilverlightSilverlight:ListBox 内的 DataGrid。将 DataGrid 列绑定到父列表框的 ItemsSource 属性。银光
【发布时间】:2011-10-25 05:06:48
【问题描述】:

我对这个有点困惑。我有一个名为“AllProducts”的集合,其中有一个名为“ProductGroups”的集合(用于分别对项目进行分组),其中包含一个名为“LineItems”(实际项目)的“产品”对象的集合。

为了进行设置,我在列表框的项的 itemtemplate 中设置了一个带有 DataGrid 的 ListBox。将列表框的 ItemsSource 设置为“ProductGroups”,并且 DataGrid(在 itemtemplate 中)有一个指向 LineItems 的 ItemsSource。

DataGrid 包含列:
"Select" -- 一个复选框和一个单选按钮
"图像" -- 字符串
"名称" -- 字符串
“描述”——字符串
"价格" -- 字符串

“ProductGroup”集合每个组都有一个名为“IsListItem”的布尔属性,它应该告诉我您是否可以为该组选择多个或单个项目(因此 DataGrid 第一列中的复选框和单选按钮)。我希望将检查按钮和单选按钮的可见性属性绑定到“IsListItem”布尔值,我已经使用带有“IsInverted”属性的 BoolToVisibility 转换器设置了该布尔值来来回切换它们。

我遇到的问题是我希望包含复选框/单选按钮的 DataGrid 的第一列绑定到 ProductGroups 的 IsLineItem(这是 ListBox 的 ItemsSource。但是由于 DataGrid 的 ItemsSource 绑定到LineItems,DataGrid 的 DataContext 设置为 LineItems,我无法访问它之外的任何内容。

这里有一些代码可以提供帮助:

列表框 XAML:

<sdk:TabItem Header="Pmt" x:Name="Payment">
                <Canvas x:Name="PaymentRoot" DataContext="{Binding Products.ProductGroups}">
                    <Rectangle Height="418" Canvas.Top="-14" Width="560" Style="{StaticResource MappingRectangleBG}" />
                    <StackPanel Canvas.Left="20" Canvas.Top="20" Width="520" Height="360">
                        <ListBox x:Name="lstProductGroups"  ItemsSource="{Binding}" ItemTemplate="{StaticResource ProductListItem}" />      
                    </StackPanel>
                </Canvas>
            </sdk:TabItem>

ListBox ItemTemplate XAML:

<sdk:DataGrid x:Name="dgLineItems" ItemsSource="{Binding LineItems}">               
            <sdk:DataGrid.Columns>
                <sdk:DataGridTemplateColumn  Header="Select">
                    <sdk:DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <CheckBox Visibility="{Binding IsListType, Converter={StaticResource boolToVisibilityConverter}}" />
                                <RadioButton Visibility="{Binding IsListType, Converter={StaticResource inverseBoolToVisibilityConverter}}" GroupName="{Binding GroupName}"/>
                            </StackPanel>                               
                        </DataTemplate>
                    </sdk:DataGridTemplateColumn.CellTemplate>
                </sdk:DataGridTemplateColumn>
                <sdk:DataGridTemplateColumn  Header="Image">
                    <sdk:DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Image Source="{Binding ImageUrl}" Height="50" />
                        </DataTemplate>
                    </sdk:DataGridTemplateColumn.CellTemplate>
                </sdk:DataGridTemplateColumn>
                <sdk:DataGridTextColumn Header="Item Name"
            Binding="{Binding Name}" />
            <sdk:DataGridTextColumn Header="Item Price"
            Binding="{Binding Price}" />
            </sdk:DataGrid.Columns>
        </sdk:DataGrid>

    </StackPanel>
</DataTemplate>

还有我的对象:

public class AllProducts
{

    public IEnumerable<ProductOptionGroup> ProductGroups;
}


public class ProductOptionGroup
{

    public string GroupName;

    public IEnumerable<Product> LineItems;

    public bool IsListType;
}


public class Product
{

    public int ID;

    public int OrdinalNumber;

    public string Name;

    public string Description;

    public Decimal Price;

    public string ImageUrl;

    public CartItemType Type;
}

(MichaelS):我尝试将其设置为父“PaymentRoot”画布的 DataContext,但它对我没有任何作用。这是我尝试过的:

<CheckBox Visibility="{Binding ElementName=PaymentRoot, Path=DataContext.IsListType, Converter={StaticResource boolToVisibilityConverter}}" />
<RadioButton Visibility="{Binding ElementName=PaymentRoot, Path=DataContext.IsListType, Converter={StaticResource inverseBoolToVisibilityConverter}}" GroupName="{Binding ElementName=PaymentRoot, Path=DataContext.GroupName}"/>

(MichaelS):这是在我的 VM 中的设置方式: 私有 AllProducts 产品;

public AllProducts Products
    {
        get
        {
            return products;
        }
        set
        {
            //Products.ProductGroups[0].LineItems[0].
            products = value;
            RaisePropertyChanged("Products");
        }
    }

【问题讨论】:

  • 我觉得下面的问题可以帮到你:(stackoverflow.com/questions/385784/…)
  • 我尝试将其设置为父“PaymentRoot”画布的 DataContext,但它没有做任何不同的事情。

标签: silverlight collections datagrid listbox itemssource


【解决方案1】:

更新: 下面的代码不起作用,因为它是在 Silverlight 3 时间框架后期发现的已知问题。 使用 column.GetCellContent(e.Row) 在 LoadingRow 事件中设置绑定应该可以解决问题。

在这种特殊情况下,您希望能够做到这一点,因为 dataGrid 本身是另一个控件的 dataTemplate。


试试这个: 用另一个Grid 包裹你的datagrid。命名它,并将其用于元素绑定。 这段代码应该可以工作:

<StackPanel>
        <Grid x:Name="GridDataHolder">
            <sdk:DataGrid x:Name="dgLineItems" ItemsSource="{Binding LineItems}">
                <sdk:DataGrid.Columns>
                    <sdk:DataGridTemplateColumn  Header="Select">
                        <sdk:DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal">
                                    <CheckBox Visibility="{Binding ElementName=GridDataHolder, Path=DataContext.IsListType, Converter={StaticResource boolToVisibilityConverter}}" />
                                    <RadioButton Visibility="{Binding ElementName=GridDataHolder, Path=DataContext.IsListType, Converter={StaticResource inverseBoolToVisibilityConverter}}" GroupName="{Binding ElementName=GridDataHolder, Path=DataContext.GroupName}"/>
                                </StackPanel>
                            </DataTemplate>
                        </sdk:DataGridTemplateColumn.CellTemplate>
                    </sdk:DataGridTemplateColumn>
                    <sdk:DataGridTemplateColumn  Header="Image">
                        <sdk:DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Image Source="{Binding ImageUrl}" Height="50" />
                            </DataTemplate>
                        </sdk:DataGridTemplateColumn.CellTemplate>
                    </sdk:DataGridTemplateColumn>
                    <sdk:DataGridTextColumn Header="Item Name"
        Binding="{Binding Name}" />
                    <sdk:DataGridTextColumn Header="Item Price"
        Binding="{Binding Price}" />
                </sdk:DataGrid.Columns>
            </sdk:DataGrid>
        </Grid>
    </StackPanel>

顺便说一句,我不确定绑定是否适用于公共成员,您可能需要将这些绑定成员更改为公共属性。

【讨论】:

  • 感谢 MichaelS,不幸的是,我尝试使用 Grid 进行元素绑定,但无济于事。我向 public 成员展示了对象的结构,但实际上我是从 Web 服务获取它并将其设置为我的 VM 中的属性。
  • @Alex,如果 listbox 绑定到 ProductGroups,那么每个 listbox 的 Datacontex。 item 将是 ProductOptionGroup。因此,包装的 Grid Datacontext 也将是 ProductOptionGroup,您应该能够将其用于元素绑定。我使用您的对象和列表框内的列表框制作了一个小示例(只是因为 listbox 的代码较少)。希望它对你有用。请更新它的进展情况。从这里下载:ParentElementBindingSample
  • 奇怪,我的代码结构和你一样。它只是不工作。我的 VM 和 IvalueConverter 中有断点,但它根本没有命中 IValueConverter。
  • 让我更困惑的是,如果我抓住复选框和单选按钮并将它们放在 DataGrid 的正上方,它会很好地工作并像它应该的那样击中 IVC。它只是未能在数据网格内部绑定
  • 是的,我觉得我真的很接近,只是没有找到“啊哈!”那一刻还没有!当我发现问题时会报告! :)
【解决方案2】:

终于搞定了!我最终要做的是完全摆脱 DataGrid,因为工具包中的许多控件似乎都有这个错误,即使通过元素绑定也无法绑定到外部。

我将 DataGrid 变成了一个 ListBox,其中包含另一个用于 LineItems 的 DataTemplate,完全自定义了它的外观,以实现与 DataGrid 相似的外观。

还要注意:我最初尝试通过元素绑定绑定到 DataTemplate 之外的 StackPanel,但它似乎有问题。因此,我在 DataTemplate 的 DataContext 中设置了网格,然后通过元素绑定将复选框和单选按钮绑定到父列表框的 dataTemplate 中的网格,这就是诀窍!

这里有一些工作代码,供以后遇到同样问题的人使用!:

<DataTemplate x:Key="LineItemsTemplate">
    <StackPanel Orientation="Horizontal">
        <StackPanel Height="100" Width="100">
            <StackPanel Height="40" Orientation="Vertical">
                <RadioButton Content="{Binding Name}" Visibility="{Binding ElementName=GridDataHolder, Path=DataContext.IsListType, Converter={StaticResource boolToVisibilityConverter}}" GroupName="{Binding ElementName=GridDataHolder, Path=DataContext.GroupName}"/>
                <CheckBox Content="{Binding Name}" Visibility="{Binding ElementName=GridDataHolder, Path=DataContext.IsListType, Converter={StaticResource inverseBoolToVisibilityConverter}}"/>
            </StackPanel>
            <Image Source="{Binding ImageUrl}" Height="50" />
        </StackPanel>
        <TextBlock TextWrapping="Wrap" Text="{Binding Description}"/>
    </StackPanel>
</DataTemplate>
<DataTemplate x:Key="ProductListItem">
    <StackPanel x:Name="GridDataHolder">
            <TextBlock TextWrapping="Wrap" Text="{Binding GroupName}" VerticalAlignment="Top" d:LayoutOverrides="Width"/>
            <ListBox x:Name="lstProductGroups"  ItemsSource="{Binding LineItems}" ItemTemplate="{StaticResource LineItemsTemplate}">
            </ListBox>
    </StackPanel>
</DataTemplate>

<sdk:TabItem Header="Pmt" x:Name="Payment">
            <Canvas>
                <Rectangle Height="418" Canvas.Top="-14" Width="560" Style="{StaticResource MappingRectangleBG}" />
                <ScrollViewer Height="389" Width="545" x:Name="PaymentRoot" DataContext="{Binding Products.ProductGroups}">
                    <StackPanel Orientation="Vertical" ScrollViewer.VerticalScrollBarVisibility="Auto" Width="500" HorizontalAlignment="Center">
                        <ListBox x:Name="lstProductGroups"  ItemsSource="{Binding}" ItemTemplate="{StaticResource ProductListItem}" />      
                    </StackPanel>
                </ScrollViewer>
            </Canvas>
        </sdk:TabItem>

感谢 MichaelS 的所有帮助!你让我走对了!

【讨论】:

  • 不客气,亚历克斯!所以你终于改变了你的dataTemplate。老实说,新的 dataTemplate 看起来更干净,可读性更强..
猜你喜欢
  • 2015-11-22
  • 1970-01-01
  • 1970-01-01
  • 2015-11-13
  • 2011-04-30
  • 1970-01-01
  • 2017-09-18
  • 1970-01-01
  • 2021-04-11
相关资源
最近更新 更多