WPF绑定到当前元素和父元素的属性

问题描述:

我对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

你应该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