DataGrid列是否可以双向绑定到字典项?

时间:2012-03-14 21:51:15

标签: c# vb.net silverlight xaml

我正在处理显示数据库数据的绑定DataGrid。如果有帮助,我正在使用Silverlight 5。目前,所有数据都存储在我的实体对象中的Dictionary中。使用绑定路径的Property[Key]语法可以正确绑定以用于显示目的。但是,当尝试在运行时更改列值时,该列的行为就像是readonly一样。

Public Class Entity
    Public Property Attributes As New Dictionary(Of String, Object)
End Class

'Sample data
Dim Entities As New List(Of Entity)
Entities.Add(New Entity With {.Attributes = New Dictionary(Of String, Object) From {{"Name", "Joe"}, {"City", "Detroit"}}})
Entities.Add(New Entity With {.Attributes = New Dictionary(Of String, Object) From {{"Name", "Bob"}, {"City", "Chicago"}}})
Entities.Add(New Entity With {.Attributes = New Dictionary(Of String, Object) From {{"Name", "Fred"}, {"City", "Dallas"}}})
MyDataGrid1.ItemsSource = Entities

<sdk:DataGrid AutoGenerateColumns="False" ItemsSource="{Binding}" Margin="12,276,12,12" Name="MyDataGrid1">
    <sdk:DataGrid.Columns>
        <sdk:DataGridTextColumn Binding="{Binding Path=Attributes[Name], Mode=TwoWay}" Header="Name" Width="Auto" />
        <sdk:DataGridTextColumn Binding="{Binding Path=Attributes[City], Mode=TwoWay}" Header="City" Width="Auto" />
    </sdk:DataGrid.Columns>
</sdk:DataGrid>

我尝试在单个实体上使用相同的绑定设置文本框,并且所有内容都按预期显示和设置值。这应排除Dictionary作为问题。

<TextBox Height="23" HorizontalAlignment="Left" Margin="12,12,0,0" Name="TextBox1" VerticalAlignment="Top" Width="120" Text="{Binding Path=Attributes[Name], Mode=TwoWay}" />

TextBox1.DataContext = Entities(1)

我还在Property[Index]上尝试了List路径语法,该语法也按预期工作。所以我想我现在不明白为什么DataGrid不允许我编辑列项。

我的另一个想法是为列使用值转换器并将密钥作为转换器参数传递。但DataGrid的行为方式与仅绑定Property[Key]的方式相同,不允许对该列进行编辑。

Public Class AttributeValueConverter
    Implements IValueConverter

    Public Function Convert(value As Object, targetType As System.Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
        Dim Attributes As Dictionary(Of String, Object) = value
        Dim Name As String = parameter
        If Attributes IsNot Nothing And Name IsNot Nothing Then
            Return Attributes(Name)
        End If
        Return Nothing
    End Function

    Public Function ConvertBack(value As Object, targetType As System.Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
        Throw New NotImplementedException
    End Function
End Class

<UserControl.Resources>
    <ps:AttributeValueConverter x:Key="AttributeValueConverter"/>
</UserControl.Resources>

<sdk:DataGridTextColumn Binding="{Binding Path=Attributes, Mode=TwoWay, Converter={StaticResource AttributeValueConverter}, ConverterParameter=Name}" Header="Name" Width="Auto" />

有没有人遇到过这种情况或者对如何实现目标有任何建议?我现在唯一想到的是将列值存储在有序列表中,并使用索引而不是键来显示它们。但我真的很想知道为什么关键不起作用。

1 个答案:

答案 0 :(得分:0)

我知道我正在回答我自己的问题,但我希望它可以帮助其他任何人解决这个问题。

在尝试使用有序列表解决我的问题时,我发现DataGridTextColumn仅允许在绑定属性为String时进行编辑。当我的示例中的词典更改为Dictionary(Of String, String)时,单元格的双向绑定和编辑按预期工作。这也可以解释为什么IValueConverter不起作用,因为它只会返回Object。我仍然想处理对象而不是字符串,所以我快速摘录了DataGridColumn

Public Class MyDataGridTextColumn
    Inherits DataGridColumn

    Private _Binding As Binding
    Public Property Binding As Binding
        Get
            Return Me._Binding
        End Get
        Set(ByVal value As Binding)
            If Me._Binding IsNot value Then
                Me._Binding = value
            End If
        End Set
    End Property

    Protected Overrides Function GenerateElement(cell As System.Windows.Controls.DataGridCell, dataItem As Object) As System.Windows.FrameworkElement
        Dim textBlock As TextBlock = New TextBlock()
        textBlock.Margin = New Thickness(4)
        textBlock.VerticalAlignment = VerticalAlignment.Center
        If Me.Binding IsNot Nothing Then
            textBlock.SetBinding(textBlock.TextProperty, Me.Binding)
        End If
        Return textBlock
    End Function

    Protected Overrides Function GenerateEditingElement(cell As System.Windows.Controls.DataGridCell, dataItem As Object) As System.Windows.FrameworkElement
        Dim textBox As TextBox = New TextBox()
        textBox.VerticalAlignment = VerticalAlignment.Stretch
        textBox.Background = New SolidColorBrush(Colors.Transparent)
        If Me.Binding IsNot Nothing Then
            textBox.SetBinding(textBox.TextProperty, Me.Binding)
        End If
        Return textBox
    End Function

End Class

当此列类用作DataGridTextColumn的替代时,我遇到的所有问题现在都消失了。使用ConvertBack时,甚至会调用IValueConverter函数。

相关问题