2017-02-28 196 views
1

我對WPF非常陌生,並且在創建綁定時嘗試使用Knockout JS作爲類比。我聽說WPF的綁定引擎更加強大,但我在Knockout中很容易陷入困境。WPF綁定到當前元素和父元素的屬性

假設我有一個具有地址集合的Person類。

public class Person 
{ 
    public string PersonId {get;set;} 
    public IList<Address> Addresses{get; set;} 
    public string FormattedName{get;set;} 
} 

public class Address 
{ 
    public string AddressId{get;set;} 
    public string Address1{get;set;} 
    public string City{get;set;} 
    public string State{get;set;} 
    public string Zip{get;set;} 
} 

假設一個頁面上,我的人集合和每個人,我想顯示所有的地址,並提供按鈕選擇一個地址。所以,我的網頁瀏覽模式是這樣的:

public class AddressSelection 
{ 
    public string PersonId{get;set;} 
    public string AddressId{get;set;} 
} 

public class PersonAddressSelectionViewModel 
{ 
    public IList<Person> People {get; set;} 

    public Person SelectedPerson {get;set;} 
    public Address SelectedAddress{get;set;} 

    public void SelectAddress(string personId, string addressId) 
    { 
     this.SelectedPerson = this.People.FirstOrDefault(x => x.PersonId == personId); 
     this.SelectedAddress = this.SelectedPerson?.Addresses.FirstOrDefault(x => x.AddressId == addressId); 
    } 

    public void SelectAddress(AddressSelection arg) 
    { SelectAddress(arg.PersonId, arg.AddressId); } 
} 

現在,我想證明顯示了每個乘客的頭部,然後爲每個地址按鈕的UI。當選擇該按鈕時,應該觸發SelectAddress函數。但是,在XAML中,我不確定如何分配綁定以同時使用父元素和當前元素屬性;它是否可以從它們創建一個對象,或者甚至只是調用一個方法並從兩個方法傳遞參數。

在淘汰賽中,你只綁定功能和訪問父上下文,如:

<!-- ko foreach: $data.people --> 
<h2 data-bind="text: formattedName"></h2> 
<ul data-bind="foreach: $data.addresses"> 
    <li> 
     <button data-bind="click: function() { $parents[1].selectAddress($parent.personId, $data.addressId); }">Select Address</button> 
    </li> 
</ul> 
<!-- /ko --> 

我似乎無法弄清楚如何做同樣的事情在XAML。

<ItemsControl Grid.Row="2" ItemsSource="{x:Bind ViewModel.People, Mode=OneWay}" 
    HorizontalAlignment="Center" Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <StackPanel Orientation="Horizontal" Margin="5"> 
       <TextBlock Style="{StaticResource TextBlockSmallStyle}" VerticalAlignment="Center" Width="180" Text="{Binding FormattedName, Mode=OneWay}" /> 
       <ItemsControl ItemsSource="{Binding Addresses}" Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> 
        <ItemsControl.ItemsPanel> 
         <ItemsPanelTemplate> 
          <VirtualizingStackPanel Orientation="Horizontal" /> 
         </ItemsPanelTemplate> 
        </ItemsControl.ItemsPanel> 
        <ItemsControl.ItemTemplate> 
         <DataTemplate> 
          <StackPanel Orientation="Horizontal"> 
           <Button Width="180" Style="{StaticResource ButtonStyle}" 
           Content="{Binding Address1}" 
           Click="SelectAddressClicked" Tag="{Binding **what to put here**}" /> 
          </StackPanel> 
         </DataTemplate> 
        </ItemsControl.ItemTemplate> 
       </ItemsControl> 
      </StackPanel> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

在後面的代碼:

SelectAddressClicked(object sender, object args) { 
    ((Button)sender).Tag as Address; // would prefer this to be something that has both the address id and person id 
} 
+0

您不需要綁定到標籤。點擊按鈕的datacontext是地址。 ((Button)sender).DataContext as Address。 –

+0

@MarkW感謝您的提示! – MPavlak

回答

0

你應該MVVM做到這一點,而不是後面的代碼

谷歌RelayCommand類實現

然後在您的視圖模型添加以下定義

public RelayCommand SelectAddressCommand { get; private set; } 

在構造

SelectAddressCommand = new RelayCommand(args => SelectAddress(args)); 

在XAML

<Button Command={Binding SelectAddressCommand} 
     CommandParameter={...} 

但根據我的理解,你可以使用的ListBox代替ItemsControl保存自己噸的麻煩。它具有SelectedItem屬性內置您可以直接綁定到您的查看模型

+0

即使我使用中繼代替後面的代碼,如何從當前上下文和父上下文構造參數? – MPavlak

+0

@MPavlak查找RelativeResource Self/FindAncestor – Steve

+0

即使有相對資源,也不會給我任何一種情況。我需要來自兩個對象的東西。如果它有所作爲,這是一個uwp應用程序,我試圖用這個問題作爲參考http://stackoverflow.com/questions/32861612/how-to-do-relativesource-mode-find-ancestor-or -equivalent-in-uwp – MPavlak