我对WPF非常陌生,我在创建绑定时尝试使用Knockout JS作为类比。我听说WPF的绑定引擎更加强大,但是我在Knockout中遇到了一些容易陷入困境的事情。
假设我有一个Person类,它有一个Addresses集合。
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中,我不确定如何分配绑定以使用父元素属性和当前元素属性;它是否可以从它们创建一个对象,甚至只是调用一个方法并从两者中传递参数fetch。
在淘汰赛中,您只需绑定该功能并访问父上下文,如:
<!-- 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 :(得分:0)
你应该用MVVM而不是代码
来做这件事 Google RelayCommand
班级实施
然后在您的视图模型中添加以下定义
public RelayCommand SelectAddressCommand { get; private set; }
构造函数中的
SelectAddressCommand = new RelayCommand( args => SelectAddress(args) );
in xaml
<Button Command={Binding SelectAddressCommand}
CommandParameter={...}
但根据我的理解,您可以使用ListBox
代替ItemsControl
来避免麻烦。它内置了SelectedItem
属性,您可以直接将其绑定到View模型