从视图中绑定到ViewModel中的复杂对象?

从视图中绑定到ViewModel中的复杂对象?

问题描述:

说,例如我有以下类型:从视图中绑定到ViewModel中的复杂对象?

public class Site 
    { 
     public string Name { get; set; } 
     public int SiteId { get; set; } 
     public bool IsLocal { get; set; } 
    } 

上述类型可以被分配在一个欢迎使用属性被保持在一个ViewModel像这样假设的对应支持字段已创建,但这里省略OFC:

public Site SelectedSite 
    { 
     get { return _selectedSite; } 
     set 
     { 
      _selectedSite = value; 
      // raise property changed etc 
     } 
    } 

在我的XAML中直正向结合将是:

  <TextBlock x:Name="StatusMessageTextBlock" 
        Width="Auto" 
        Height="Auto" 
        Style="{StaticResource StatusMessageboxTextStyle}" 
        Text="{Binding MessageToDisplay, 
            Mode=OneWay, 
            UpdateSourceTrigger=PropertyChanged}" /> 

可以通过使用点符号语法扩展绑定?例如:

  <TextBlock x:Name="StatusMessageTextBlock" 
        Width="Auto" 
        Height="Auto" 
        Style="{StaticResource StatusMessageboxTextStyle}" 
        **Text="{Binding SelectedSite.Name,** 
            Mode=OneWay, 
            UpdateSourceTrigger=PropertyChanged}" /> 

似乎是一个有趣的功能,但我的直觉是没有一个我的DC是在运行时被分配所以在设计时或编译时,我看不到任何线索,可以实现此功能,或不?

纠正我,如果误解了一个复杂的对象是什么,我简化了我的这个问题。

当然这是可能的。但是,WPF需要知道路径上的任何属性何时发生更改。为此,您需要实施INotifyPropertyChanged(或其他支持的机制)。在你的例子中,Site和包含SelectedSite的VM都应该实现更改通知)。

这里是你如何可以实现你在你的问题中指定的功能:

// simple DTO 
public class Site 
{ 
    public string Name { get; set; } 
    public int SiteId { get; set; } 
    public bool IsLocal { get; set; } 
} 

// base class for view models 
public abstract class ViewModel 
{ 
    // see http://kentb.blogspot.co.uk/2009/04/mvvm-infrastructure-viewmodel.html for an example 
} 

public class SiteViewModel : ViewModel 
{ 
    private readonly Site site; 

    public SiteViewModel(Site site) 
    { 
     this.site = site; 
    } 

    // this is what your view binds to 
    public string Name 
    { 
     get { return this.site.Name; } 
     set 
     { 
      if (this.site.Name != value) 
      { 
       this.site.Name = value; 
       this.OnPropertyChanged(() => this.Name); 
      } 
     } 
    } 

    // other properties 
} 

public class SitesViewModel : ViewModel 
{ 
    private readonly ICollection<SiteViewModel> sites; 
    private SiteViewModel selectedSite; 

    public SitesViewModel() 
    { 
     this.sites = ...; 
    } 

    public ICollection<SiteViewModel> Sites 
    { 
     get { return this.sites; } 
    } 

    public SiteViewModel SelectedSite 
    { 
     get { return this.selectedSite; } 
     set 
     { 
      if (this.selectedSite != value) 
      { 
       this.selectedSite = value; 
       this.OnPropertyChanged(() => this.SelectedSite); 
      } 
     } 
    } 
} 

而且你的观点可能会是这个样子(假设SitesViewModel类型的DataContext):

<ListBox ItemsSource="{Binding Sites}" SelectedItem="{Binding SelectedSite}"/> 
+0

嗯......你是说我的简单类型'网站'需要实现'INotifyPropertyChanged'界面? – IbrarMumtaz 2012-04-19 19:29:22

+0

@IbrarMumtaz:如果你有改变的属性(比如'Name'),那么是的。如果类型中的所有属性都是只读的,那么不需要实现'INotifyPropertyChanged',因为没有属性会改变。 – 2012-04-19 19:31:18

+0

我正在使用MVVM Light框架,这使得事情变得更容易,但我不熟悉实现此接口的自定义类型的技术,我一直认为这是您的ViewModels必须执行此操作。有一篇文章解释了这种方法? – IbrarMumtaz 2012-04-19 19:31:30

下面是什么对我有效:

 public Site SelectedSite 
     { 
      get { return _selectedSite; } 
      set 
      { 
       _selectedSite = value; 
       RaisePropertyChanged("SelectedSite"); 
      } 
     } 

我ñ我的XAML我是能够做到:

 <TextBox Name="tbSiteName" 
       Width="250" 
       Height="30" 
       Margin="0" 
       HorizontalAlignment="Left" 
       VerticalAlignment="Top" 
       IsReadOnly="True" 
       Style="{StaticResource MainTextBoxStyle}" 
       Text="{Binding SelectedSite.Name, 
          Mode=OneWay, 
          UpdateSourceTrigger=PropertyChanged}" /> 

这允许您访问数据成员关闭网站类型,而无需创建一个包裹每个数据成员的站点类型的各个属性。然后,单个控件可以绑定到VM中声明的每个属性。以一对一的方式,这个问题可能变得相当冗长。附加到上面显示的TextBox控件的Text属性的绑定扩展显示我们不绑定到简单的直接属性,而是实际绑定到自定义类型。潜在地消除了创造更多公共财产的需要。

+0

您还将视图与您的域模型绑定在一起。我会建议反对这一点,就像我在答案中所做的那样。几乎不可避免地,您会发现 - 您迟早需要使用您的域数据打包的额外的,特定于查看的信息。如果你有一堆代码直接绑定到域对象,它会使重构工作变得更加困难。尽管视图模型最初并不向域对象添加任何内容,但最好咬住子弹并仅使用视图模型来处理所有事情。 – 2012-04-20 14:12:07

+0

我明白你来自哪里......我将保持我的工作原样,并让这个问题自然而然地出现。我学习的最佳方式就是亲眼目睹问题。 =) – IbrarMumtaz 2012-04-24 08:43:25