2012-04-19 77 views
4

說,例如我有以下類型:從視圖中綁定到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是在運行時被分配所以在設計時或編譯時,我看不到任何線索,可以實現此功能,或不?

糾正我,如果誤解了一個複雜的對象是什麼,我簡化了我的這個問題。

回答

5

當然這是可能的。但是,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

0

下面是什麼對我有效:

 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