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
}
答
你应该MVVM做到这一点,而不是后面的代码
谷歌RelayCommand
类实现
然后在您的视图模型添加以下定义
public RelayCommand SelectAddressCommand { get; private set; }
在构造
SelectAddressCommand = new RelayCommand(args => SelectAddress(args));
在XAML
<Button Command={Binding SelectAddressCommand}
CommandParameter={...}
但根据我的理解,你可以使用的ListBox
代替ItemsControl
保存自己吨的麻烦。它具有SelectedItem
属性内置您可以直接绑定到您的查看模型
您不需要绑定到标签。点击按钮的datacontext是地址。 ((Button)sender).DataContext as Address。 –
@MarkW感谢您的提示! – MPavlak