WPF - 带按钮的列表视图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4921046/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF - Listview with button
提问by Filipe Sguarizi Panceri
i have a listview template and one column is a button. I need selected item when i click in this button. How i can do this ??
我有一个列表视图模板,一列是一个按钮。单击此按钮时,我需要选定的项目。我怎么能做到这一点??
回答by Zamboni
To cature the selected ListView item inside a button pressed event you can leverage the MVVM pattern. In my ListView, in the XAML, I bind the ItemsSource and SelectedItem to a ViewModel class. I also bind my button Command in the template to RunCommand in the ViewModel.
要在按钮按下事件中捕获选定的 ListView 项目,您可以利用 MVVM 模式。在我的 ListView 中,在 XAML 中,我将 ItemsSource 和 SelectedItem 绑定到一个 ViewModel 类。我还将模板中的按钮 Command 绑定到 ViewModel 中的 RunCommand。
The tricky part is getting the binding correct from the template to the active DataContext.
棘手的部分是从模板到活动 DataContext 的正确绑定。
Once you do this you can capture the SelectedCustomer inside the RunCommand that gets executed when the button gets pressed.
执行此操作后,您可以在按下按钮时执行的 RunCommand 中捕获 SelectedCustomer。
I've included some of the code to help get you started. You can find implementations of ViewModelBase and DelegateCommand via Google.
我已经包含了一些代码来帮助您入门。您可以通过 Google 找到 ViewModelBase 和 DelegateCommand 的实现。
Here is the XAML:
这是 XAML:
<Window x:Class="ListViewScrollPosition.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Main Window" Height="400" Width="400">
<Grid>
<ListView ItemsSource="{Binding Path=Customers}"
SelectedItem="{Binding Path=SelectedCustomer}"
Width="Auto">
<ListView.View>
<GridView>
<GridViewColumn Header="First Name">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Margin="6,2,6,2">
<TextBlock Text="{Binding FirstName}"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Last Name">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Margin="6,2,6,2">
<TextBlock Text="{Binding LastName}"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Address">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Margin="6,2,6,2">
<Button Content="Address"
Command="{Binding
Path=DataContext.RunCommand,
RelativeSource=
{RelativeSource FindAncestor,
AncestorType={x:Type ItemsControl}}}"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
Here is the ViewModel:
这是视图模型:
using System.Collections.ObjectModel;
using System.Windows.Input;
using ListViewScrollPosition.Commands;
using ListViewScrollPosition.Models;
namespace ListViewScrollPosition.ViewModels
{
public class MainViewModel : ViewModelBase
{
public ICommand RunCommand { get; private set; }
public MainViewModel()
{
RunCommand = new DelegateCommand<object>(OnRunCommand, CanRunCommand);
_customers = Customer.GetSampleCustomerList();
_selectedCustomer = _customers[0];
}
private ObservableCollection<Customer> _customers =
new ObservableCollection<Customer>();
public ObservableCollection<Customer> Customers
{
get
{
return _customers;
}
}
private Customer _selectedCustomer;
public Customer SelectedCustomer
{
get
{
return _selectedCustomer;
}
set
{
_selectedCustomer = value;
OnPropertyChanged("SelectedCustomer");
}
}
private void OnRunCommand(object obj)
{
// use the SelectedCustomer object here...
}
private bool CanRunCommand(object obj)
{
return true;
}
}
}
Here is where I link in the ViewModel to the View:
这是我在 ViewModel 中链接到视图的地方:
public partial class MainView : Window
{
public MainView()
{
InitializeComponent();
DataContext = new ViewModels.MainViewModel();
}
}
回答by b_levitt
Example with a regular click event in the code behind:
后面的代码中带有常规点击事件的示例:
<ListView Height="167.96" VerticalAlignment="Top" ItemsSource="{Binding FulfillmentSchedules}" SelectedItem="{Binding SelectedFulfillmentSchedule}">
<ListView.View>
<GridView>
<GridViewColumn Header="Request">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}-{1}-{2}">
<Binding Path="Template.ProjectNumber" />
<Binding Path="Template.JobNumber" />
<Binding Path="Template.RequestId" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Template" DisplayMemberBinding="{Binding Template.Name}"/>
<GridViewColumn Header="Start Date" DisplayMemberBinding="{Binding StartDate}"/>
<GridViewColumn Header="Records" DisplayMemberBinding="{Binding Parameters.Records}"/>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Name="BtnYourButton" Content="Your Button" Click="BtnYourButton_Click" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
Code behind:
后面的代码:
private void BtnYourButton_Click(object sender, RoutedEventArgs e)
{
var boundData= (YourBoundDataType)((Button)sender).DataContext;
//do what you need to do here, including calling other methods on your VM
}
Note: While I certainly appreciate MVVM, I've come to accept that there is a pretty steep slope of dimminishing returns once you cross into actions and messaging between the form and the VM, so I use it only in cases of complex relationships between VMs or large singular VMs. For CRUD style data-centric applications I prefer to handle actions and message relay with the code behind.
注意:虽然我当然很欣赏 MVVM,但我已经开始接受,一旦你进入表单和 VM 之间的操作和消息传递,就会有一个非常陡峭的收益递减斜率,所以我只在 VM 之间存在复杂关系的情况下使用它或大型单一虚拟机。对于 CRUD 风格的以数据为中心的应用程序,我更喜欢使用背后的代码来处理操作和消息中继。