了解DataBinding

时间:2012-01-23 15:25:18

标签: c# .net wpf xaml

我是WPF和整个数据绑定的新手。我读了几篇帖子,我对如何将数据绑定到UI元素感到很困惑。

我看到一篇帖子这样做:

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Name="myWindow">
   <Grid>
       <TextBox Text="{Binding Path=Speed, ElementName=myWindow}" />
   </Grid>
</Window>

这假定Speed是代码隐藏文件中定义的属性/成员。其他一些人使用静态资源命名绑定,并引用此名称和其他名为DataContext的人用于绑定。现在,因为我是WPF数据绑定的新手,所以我不确定是否存在关于使用哪种数据绑定的最佳实践方法。

基本上我想知道为什么必须将几个类属性定义为底层视图模型的连接器,我虽然这些东西更“动态”。

我的目标是只拥有XAML文件,而无需在* .xaml.cs代码后面添加任何内容。例如:我有一个名为MainWindowViewModel的类(它将代表我的ViewModel),其成员类型为ObservableCollection<string>,我想将ListBox(在我的视图中)绑定到此集合。到目前为止我使用这个工作的唯一方法是使用第一个案例ElementName,我必须在视图类中添加一个属性作为一种连接器。就像这样:

MainWindow.xaml:

<Window x:Class="Sample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Name="MW" Title="MainWindow" Height="419" Width="463">
    <Grid>
        <ListBox ItemsSource="{Binding ElementName=MW, Path=ListerResultConnector}" />
    </Grid>
</Window>

MainWindow.xaml.cs:

private ObservableCollection<string> mListerResultData = MainWindowViewModel.Instance.RetrievalStringResults;
public ObservableCollection<string> ListerResultConnector
{
    get { return mListerResultData; }
}

我的问题是,如果存在一种更智能的方法将数据绑定到我的UI,就像使用代码隐藏文件中的更多“连接器”属性一样。

6 个答案:

答案 0 :(得分:2)

您的ViewModel应设置为视图的DataContext。那你就不需要任何其他的连接器&#34;在代码隐藏中。绑定实际上是指DataContext,如果你没有设置它,它仍然是&#39;这个&#39;,它对应于你的代码隐藏文件(这只是你视图的一部分)。

另外,请查看:WPF Apps With The Model-View-ViewModel Design Pattern

你应该首先获得WPF及其绑定基础,但是一旦你理解了这些,我建议看看Caliburn Micro及其基于约定的绑定,事件处理和其他使你的代码更多的功能清洁剂。

答案 1 :(得分:1)

您的{Binding ElementName=MW表示您绑定到窗口本身,因此您的DataContext是窗口,您需要在该窗口中定义您实现的任何属性(在您的代码后面 - 您的“连接器” “)。

您需要删除ElementName=MW位并将ViewModel指定为DataContext,以便直接绑定到其属性。如何执行此操作取决于您是使用“ViewModel First”还是“View First”

在View中,首先在创建视图时手动将DataContext分配给View in code。

首先在ViewModel中,在XAML中创建一个DataTemplate,将View绑定到特定的ViewModel。我认为ViewModel首先更常见。 Darjan发布的链接可以帮助您了解其中的差异。

答案 2 :(得分:1)

您应该使用单独的ViewModel类(WindowViewModel)来表示Window的数据上下文(Window.DataContext)。

我发现使用MVVM Light toolkit并关注网站上的一些视频帮助我填补了空白。在开始之前花些时间学习它并且它将开始沉入。IoC containers也与MVVM + WPF混合用于目录管理&amp;视图模型的生命周期管理和改进的设计时体验(可混合性)。

不需要工具包,有时会妨碍学习模式。一旦理解了它,就应该利用工具包来加速开发过程。这是comparison of various MVVM toolkits

答案 3 :(得分:1)

绑定通常包含两部分:源对象和属性名称

在绑定中指定ElementName时,您将设置Source对象。指定绑定源对象的其他方法包括RelativeSourceSource属性。您也可以保留绑定的源对象未定义,在这种情况下,它将使用当前对象的DataContext。源对象可以是在WPF的VisualTree中找到的UI元素,也可以是控件的DataContext

中的类对象

指定Path时,您告诉绑定要使用的属性。您也可以将此属性留空以绑定到当前对象的DataContext

DataContext是存储在控件后面的数据对象。这通常是ModelViewModel(如果使用MVVM),尽管它几乎也可以是任何对象,例如UI元素。

在你的例子中

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Name="myWindow">
   <Grid>
       <TextBox Text="{Binding Path=Speed, ElementName=myWindow}" />
   </Grid>
</Window>

您告诉绑定它的源对象是名为myWindow的可视树中的UI元素,该属性称为Speed。由于名为myWindow的对象属于Window类型,因此只有Window类实际上具有名为Speed的属性时,此绑定才有效。

这里有很多答案建议你切换到使用MVVM设计模式,我同意如果你正在使用WPF,你应该尝试使用MVVM。由于您将应用程序逻辑与UI分离,因此编码变得更加简单。如果您有兴趣,我会有一个simple MVVM example posted on my blog来解释该设计模式的基础知识。

答案 4 :(得分:1)

最简单的方法是:

<Window x:Class="WpfApplication4.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ctrl="clr-namespace:WpfApplication4"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <ctrl:MainWindowViewModel x:Key="mym" />
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource mym}}">
    <ListBox ItemsSource="{Binding Path=MyListProp}" />
</Grid>

上面的示例执行以下操作:

  1. 创建ViewModel的新对象作为窗口的资源
  2. 将视图模型指定为窗口的DataContext(根网格更精确)
  3. 将列表框绑定到ViewModel ObservableCollection属性MyListProp。
  4. 尝试通过使用msdn库来熟悉绑定类的属性以完全理解此示例。 WPF 4 Unleashed - Adam Nathan是wpf初学者的重要资源。第13章 - 数据绑定应涵盖您可能想要了解的有关绑定的所有内容。

答案 5 :(得分:1)

是的,如果不是令人困惑的话,Binding就没什么了不起的。

This example from msdn可能会有所帮助。注意如何在DataContext“级别声明Window” - 在这种情况下它是复杂/复合对象,因此Window子元素'{Binding}声明隐含地相对于“父”级别“DataContext

我们得到的主要好处是,当DataContext设置为给定对象时,所有“子元素”数据绑定都自动保持同步。我们可以使用此模式在UI Control结构层次结构中的任意/多个级别控制此同步。

引擎盖下的收藏装订

底线是您的收藏必须至少实施IList。许多.NET Collection类都是“绑定就绪”。

以下是msnd doc on ObservableCollection

的引用
  

在实现自己的集合之前,请考虑使用ObservableCollection或其中一个现有集合类,例如List,Collection和BindingList等。如果您有高级方案并且想要实现自己的集合,请考虑使用IList,它提供可以通过索引单独访问的非泛型对象集合。实现IList可以使用数据绑定引擎提供最佳性能。

最后,双向绑定需要IBinding list vs IList