WPF+Prism中DataTemplate内按钮绑定ViewModel命令失败的问题求助
WPF+Prism中DataTemplate内按钮绑定ViewModel命令失败的问题求助
你好呀,这个问题我之前做Prism项目时也踩过坑,核心原因很好理解:DataTemplate里的元素默认DataContext是集合中的单个Person对象,而你的ButtonClickedCommand是定义在MainWindowViewModel里的,直接写{Binding ButtonClickedCommand}相当于在Person类里找这个命令,肯定找不到呀😅
下面给你几个简单可行的解决办法,选一个你觉得顺手的就行:
方法一:通过RelativeSource绑定父级控件的DataContext
ListBox的DataContext是MainWindowViewModel,我们可以通过RelativeSource找到ListBox,再绑定它的DataContext里的命令。如果需要把当前点击的Person对象传给命令,还可以加上CommandParameter。
修改后的Button XAML代码如下:
<Button Content="{Binding Address}" Width="50"> <b:Interaction.Triggers> <b:EventTrigger EventName="Click"> <prism:InvokeCommandAction Command="{Binding DataContext.ButtonClickedCommand, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}" CommandParameter="{Binding}" /> </prism:InvokeCommandAction> </b:EventTrigger> </b:Interaction.Triggers> </Button>
如果需要接收参数,ViewModel里的命令也要对应修改:
// 把命令改成泛型版本,接收Person类型参数 public DelegateCommand<Person> ButtonClickedCommand { get; private set; } public MainWindowViewModel() { People = new ObservableCollection<Person> { // 你的Person实例初始化代码... }; // 初始化命令时关联带参数的方法 ButtonClickedCommand = new DelegateCommand<Person>(BtnClicked); } // 方法参数改成Person类型,就能拿到点击的对象了 public void BtnClicked(Person clickedPerson) { // 这里可以处理点击的Person,比如打印它的Name Console.WriteLine($"点击了{clickedPerson.Name}的按钮"); int a = 1; int b = 2; int c = 3; }
方法二:通过ElementName绑定Window的DataContext
给Window起个名字,然后直接绑定它的DataContext里的命令,这种方式也很直观:
首先给Window添加x:Name属性:
<Window x:Class="TestWpf.Views.MainWindow" ... x:Name="RootMainWindow" prism:ViewModelLocator.AutoWireViewModel="True" >
然后Button的Command绑定改成:
<prism:InvokeCommandAction Command="{Binding DataContext.ButtonClickedCommand, ElementName=RootMainWindow}" CommandParameter="{Binding}" />
这种方式和方法一原理一样,都是找ViewModel所在的DataContext,选哪种看你个人习惯~
注意点
- 确认AncestorType或者ElementName对应的控件DataContext确实是
MainWindowViewModel,比如ListBox的ItemsSource是{Binding People},说明它的DataContext就是ViewModel,所以没问题。 - 如果不需要传当前Person对象,就去掉
CommandParameter,ViewModel里的命令用无参的DelegateCommand就可以。
这样修改后,点击按钮应该就能成功触发ViewModel里的BtnClicked方法啦😉
内容来源于stack exchange
相关产品推荐
相关产品推荐

