MVVM-Light,从数据网格列模板内的按钮触发事件

时间:2010-07-22 02:41:00

标签: silverlight mvvm-light

MVVM灯很高兴学习,但在这里我被卡住了。问题是事件发生。

在下面的代码中,一个按钮可以工作并触发事件。另一个按钮不是。输出中未报告绑定错误。我有什么明显的遗失吗?

<Grid x:Name="LayoutRoot">...
<StackPanel>
  <Button Content="THIS BUTTON WORKS">
    <i:Interaction.Triggers>
      <i:EventTrigger EventName="Click">
        <Command:EventToCommand Command="{Binding DataContext.HandleAddQuestionActionCommand, ElementName=LayoutRoot, Mode=OneWay}" PassEventArgsToCommand="True"/>
      </i:EventTrigger>
    </i:Interaction.Triggers>
  </Button>
  <sdk1:DataGrid ItemsSource="{Binding QuestionActions}" AutoGenerateColumns="False" >
    <sdk1:DataGrid.Columns>
      <sdk1:DataGridTextColumn Binding="{Binding Answer.Name}" Header="Answer"/>
        <sdk1:DataGridTemplateColumn Header="Edit">
          <sdk1:DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
              <Button Content="THIS BUTTON DONT WORK" >
                <i:Interaction.Triggers>
                  <i:EventTrigger EventName="Click">
                    <Command:EventToCommand Command="{Binding DataContext.HandleEditQuestionActionCommand, ElementName=LayoutRoot, Mode=OneWay}" PassEventArgsToCommand="True"/>
                  </i:EventTrigger>
                </i:Interaction.Triggers>
              </Button>
            </DataTemplate>
          </sdk1:DataGridTemplateColumn.CellTemplate>
        </sdk1:DataGridTemplateColumn>
    </sdk1:DataGrid.Columns>
  </sdk1:DataGrid>
</StackPanel>

ViewModel代码:

public RelayCommand<RoutedEventArgs> HandleAddQuestionActionCommand {
    get; private set;
}
public RelayCommand<RoutedEventArgs> HandleEditQuestionActionCommand {
    get; private set;
}


HandleAddQuestionActionCommand = new RelayCommand<RoutedEventArgs>(e =>{...});
HandleEditQuestionActionCommand = new RelayCommand<RoutedEventArgs>(e =>{...});

3 个答案:

答案 0 :(得分:11)

您的数据上下文在DataGrid DataGridTemplateColumn中丢失,因为DataGrid.Columns不是依赖项属性。因此,您不能在DataGridTemplateColumn中使用元素到元素的数据绑定。

然而,由于MVVM Light Toolkit的ViewModelLocator,这很容易解决。

我不知道您的ViewModel被调用了什么,但假设它是MainViewModel,您可以将按钮绑定更改为:

<sdk1:DataGridTemplateColumn Header="Edit">
    <sdk1:DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Button Content="THIS BUTTON WILL WORK NOW ;-)" >
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="Click">
                        <Command:EventToCommand Command="{Binding Source={StaticResource Locator},
                                                                  Path=MainViewModel.HandleEditQuestionActionCommand}"
                                                PassEventArgsToCommand="True" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </Button>
        </DataTemplate>
    </sdk1:DataGridTemplateColumn.CellTemplate>
</sdk1:DataGridTemplateColumn>

答案 1 :(得分:0)

DataGrid中的按钮具有QuestActions的DataContext,因为Binding基于DataGrid的ItemSource属性。在这种情况下,您需要找到DataGrid本身的DataContext(或UserControl或其中具有Command的DataContext中的任何父级)才能访问您的Command:

<Command:EventToCommand 
Command="{Binding RelativeSource={RelativeSource FindAncestor, 
AncestorType={x:Type sdk1:DataGrid}}, 
Path=DataContext.ViewSchemaCommand, Mode=OneWay}" 
PassEventArgsToCommand="True" />

答案 2 :(得分:0)

此解决方案仅适用于静态视图模型。查看Dan Whalin的页面,寻找替代答案。 http://weblogs.asp.net/dwahlin/archive/2009/08/20/creating-a-silverlight-datacontext-proxy-to-simplify-data-binding-in-nested-controls.aspx

您可以创建这样的资源(不要忘记您的参考资料):

<UserControl.Resources>
     <controls:DataContextProxy x:Key="DataContextProxy" />
</UserControl.Resources>

<sdk:Page.Resources>
    <controls:DataContextProxy x:Key="DataContextProxy"/>
</sdk:Page.Resources>

在控件中使用如下:

<sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
        <Button Content="Content">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <cmd:EventToCommand Command="{Binding Source={StaticResource DataContextProxy}, Path=DataSource.MyCommand}"
                                        CommandParameter="{Binding Path=SomeValue}"
                                        PassEventArgsToCommand="False">     
                    </cmd:EventToCommand>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
    </DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>

视图模型 定义RelayCommand:

public RelayCommand<object> MyCommand { get; set; }

在构造函数中设置RelayCommand:

MyCommand = new RelayCommand<object>((e) =>
        {
            if (e != null && e is int)
            {
                int varName = int.Parse(e.ToString());

                //DoSomething...
            }
        });