无法围绕wpf数据绑定

时间:2009-05-19 15:18:35

标签: .net wpf data-binding observablecollection

我的情景: wpf表单有一个文本框和一个wpf工具箱datagrid。 在文本框中输入文本后,我的服务会返回IEnumerable<TranslationItem>个项目。我希望我的datagrid显示此服务的结果。

我试着用谷歌搜索,但我无法正确对待它。我只是开始学习WPF,而且大多数使用的术语都没有我 我收集到的是我应该把我的服务结果放在一个ObservableCollection中,没有汗水。 但后来我想以某种方式将它绑定到我的数据网格。我怎样才能做到这一点?网格将如何知道要生成哪些列?

4 个答案:

答案 0 :(得分:3)

  

我收集的是我应该将我的服务结果放在ObservableCollection中,没有汗水。但后来我想以某种方式将它绑定到我的数据网格。我怎么能这样做?

最简单的方法是将DataGrid的ItemsSource属性设置为ObservableCollection。

  

网格将如何知道要生成哪些列?

DataGrid反映该集合中的对象,并为找到的每个公共属性创建一列。有关详细信息,请参阅here

如果直接设置ItemsSource属性,那么它实际上不是wpf绑定。这是我在WPF中开始数据绑定时发现的三个链接。

Bea Stollnitz: What does “{Binding}” mean?
WPF Basic Data Binding FAQ
MSDN: Data Binding How-to Topics

答案 1 :(得分:2)

虽然可以使用ObservableCollection,但根据它的使用方式,你不会从中获得任何好处。 ObservableCollection的关键特性是它实现了INotifyCollectionChanged。该接口的作用是提供一种通知机制来告诉UI属性已更改。由于ObservableCollection已经实现了这一点,如果将DataGrid,ListBox,ItemsControl等的ItemSource属性绑定到此类型的集合,它将在项目添加/删除/替换/移动/重置时自动更新UI。因此,每次要使用新的IEnumerable结果集更新集合时,都必须先清除集合,然后添加新结果。

但是,在这种情况下,我会建议另一个选项是ObservableCollection。它是使用一种叫做ObjectDataProvider的东西。使用这个我们可以完全避免代码背后的问题,而且整体上更加清晰。所以我们在某处提供服务,在本例中是在我的Window.xaml.cs

public class TranslationService
{
    public IEnumerable<string> Translate(string s)
    {
        return s.ToCharArray().Select(c => c.ToString());
    }
}

与您描述的服务类似,它从文本框中获取一个字符串,并返回一个IEnumerable。现在,在XAML中,我们可以使用此服务并对其进行调用。

在窗口中,我们添加了服务所在位置的命名空间:

 xmlns:local="clr-namespace:WpfApplication4"

现在,在我们的Window.Resources(或UserControl或其他任何地方)中,我们可以引用我们的服务。一旦我们将服务作为资源公开,我们就可以创建一个ObjectDataProvider来公开我们希望使用的Translate方法。

<Window.Resources>
    <local:TranslationService x:Key="MyTranslationService" />
    <ObjectDataProvider x:Key="MyProvider"
                        ObjectInstance="{StaticResource MyTranslationService}"
                        MethodName="Translate">
        <ObjectDataProvider.MethodParameters>
            ""
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
</Window.Resources>

ObjectDataProvider是我们服务的键,并使用String参数调用Translate方法。现在我们所要做的就是让它回应我们的文本框。

我们可以通过使用一些Binding属性来实现。我们希望TextBox中的TextProperty绑定到ObjectDataProvider,因此我们将Source属性设置为指向它。我们要在Path中绑定的ObjectDataProvider部分是MethodParameter。现在,我们将其设置为直接绑定到该属性的源,并且仅以单向传播,这意味着ObjectDataProvider的方法参数不会更新TextBox的文本。最后,我们可以将UpdateSourceTrigger设置为PropertyChanged,告诉绑定在对象数据提供程序中设置我们绑定的源,只要文本有任何更改。

<StackPanel>
        <TextBox TextChanged="OnTextChanged"
            Text="{Binding Source={StaticResource MyProvider}, Path=MethodParameters[0], BindsDirectlyToSource=True, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}" />
        <ListBox ItemsSource="{Binding Source={StaticResource MyProvider}}" />
    </StackPanel>

剩下的就是在Grid中设置ItemsSource,或者在这种情况下设置一个简单的ListBox。

关于DataGrid的最后部分: 如果您使用的是WPFToolkit的数据网格,它确实具有可以通过属性设置的自动生成功能,您可以在其上找到更多信息here

答案 2 :(得分:0)

将网格的DataSource(甚至DataContext)设置为Observable Collection。

我不熟悉那个数据网格,但是大多数网格都有选项可以将Observable Collection中类型的所有公共属性公开为列,或者在XAML中显式设置列布局以及其中一个属性。列定义是用于列数据的对象的属性。

e.g。使用Infragistics数据网格

                <igDP:Field Name="OrderSize" Label="Order Size">
                    <igDP:Field.Settings >
                        <igDP:FieldSettings CellWidth="75">
                            <igDP:FieldSettings.EditorStyle>
                                <Style TargetType="{x:Type Editors:ValueEditor}" >
                                    <Style.Setters>
                                        <Setter Property="Format" Value="#,##0"/>
                                    </Style.Setters>
                                </Style>
                            </igDP:FieldSettings.EditorStyle>
                        </igDP:FieldSettings>
                    </igDP:Field.Settings>
                </igDP:Field>

名称是您在要使用的对象上设置属性的位置。

答案 3 :(得分:0)

您的网格可以直接构建列,也可以指定所需的列类型。如果你看这个video,它会解释它。这是针对VS2010的,但VS2008的基本原理是相同的 - 虽然实现略有不同,因为它不是那么集成。

至于如何绑定,将包含项目的ObservableCollection分配给网格的ItemsSource属性。