Page.Resources中ListBoxItem内Button命令失效,如何正确实现命令绑定?
当给位于Page.Resources的ListBoxItem样式中的Button添加Command后,点击按钮无任何响应;但将Button放置在默认Grid中时,Command可以正常工作。补充说明:直接点击按钮本身功能正常,但出于MVVM规范无法采用此方式。
相关代码
XAML代码
<Page x:Class="kkRedux.MVVM.View.SpecialView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:kkRedux.MVVM.View" xmlns:viewModel="clr-namespace:kkRedux.MVVM.ViewModel" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800" Title="SpecialView"> <Page.DataContext> <viewModel:SpecialViewModel /> </Page.DataContext> <Page.Resources> <Style TargetType="ListBoxItem" x:Key="DieStyle"> <Setter Property="Template"> <Setter.Value> <ControlTemplate> <Grid Margin="11"> <Button Content="Click Mey" Width="100" Height="100" Background="Black" Command="{Binding DownloadCommand}"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> <ItemsPanelTemplate x:Key="panelTemplate"> <WrapPanel /> </ItemsPanelTemplate> </Page.Resources> <Grid> <!--ItemsSource ommited--> <ListBox Name="specialListBox" ItemContainerStyle="{StaticResource DieStyle}" ItemsPanel="{StaticResource panelTemplate}" Background="Transparent"/> <!--this Command is working--> <Button Content="Click" Height="100" Width="100" Command="{Binding DownloadCommand}"/> </Grid> </Page>
ViewModel代码
internal class SpecialViewModel { public RelayCommand DownloadCommand { get; set; } public SpecialViewModel() { DownloadCommand = new RelayCommand<string>(o => Download(o)); } private void Download(string arg) { MessageBox.Show(arg); } }
原因分析
ListBoxItem的DataContext默认是绑定的集合中的单个数据项,而不是页面的SpecialViewModel。所以样式里的Button用{Binding DownloadCommand}时,会去当前ListBoxItem绑定的数据项里找这个命令,自然找不到,导致点击无响应。而Grid中的Button继承的是页面的DataContext,所以能正确绑定到ViewModel的DownloadCommand。
解决方法
方法一:通过RelativeSource绑定到页面的ViewModel
修改样式内Button的Command绑定,通过RelativeSource找到页面的DataContext:
<Button Content="Click Mey" Width="100" Height="100" Background="Black" Command="{Binding DataContext.DownloadCommand, RelativeSource={RelativeSource AncestorType={x:Type Page}}}" CommandParameter="{Binding}"/>
这里CommandParameter="{Binding}"是把当前ListBoxItem的数据项作为参数传递给命令,对应ViewModel里的RelayCommand<string>。
方法二:使用ElementName绑定
先给Page设置一个名字:
<Page x:Class="kkRedux.MVVM.View.SpecialView" ... x:Name="SpecialPage">
然后修改Button的Command绑定:
<Button Content="Click Mey" Width="100" Height="100" Background="Black" Command="{Binding DataContext.DownloadCommand, ElementName=SpecialPage}" CommandParameter="{Binding}"/>
两种方法都能让样式里的Button正确绑定到页面ViewModel的命令,点击后就能触发Download方法了。
内容的提问来源于stack exchange,提问作者Egor Bobrov
相关产品推荐
相关产品推荐

