【问题标题】:MVVM-Light, firing events from a button inside a data grid column templateMVVM-Light,从数据网格列模板内的按钮触发事件
【发布时间】:2010-07-22 02:41:00
【问题描述】:

MVVM light 学习起来很愉快,但在这里我被卡住了。问题是事件触发。

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

<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 =>{...});

【问题讨论】:

    标签: silverlight mvvm-light


    【解决方案1】:

    您的数据上下文丢失在 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>
    

    【讨论】:

    • 这正是我所需要的!谢谢,有了这个,MVVM-light 在所有场景中仍然是一种简单而优雅的 Silverlight 方法。再次感谢
    • 此示例是在 Silverlight 中创建的,而不是 WPF。
    • 感谢您的回答,这就像一个魅力。一直在拔掉我留下的小头发!
    【解决方案2】:

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

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

    【讨论】:

    • 如果我错了,请纠正我,但 FindAncestor 和 AncestorType 东西不是仅在 WPF 中可用吗?
    • 理论是正确的,你需要绑定到父DataGrid的DataContext。在此线程中,您可能想查看一个解决方法:forums.silverlight.net/forums/p/163476/367975.aspx
    • 真的吗?我没有意识到 FindAncestor 和 AncestorType 是 WPF-only。
    • 这里是有问题的行: 如果我纠正我我错了,但 ELEMENTNAME=LayoutRoot, Path=DataContext..... 是否足以将事件绑定到 viewmodel 中的属性而不需要 RelativeSource?
    • @pete - 没有。请参阅几分钟前@Matt Casto 的回答,这应该有助于解决此 Silverlight 问题。
    【解决方案3】:

    此解决方案仅适用于静态视图模型。查看 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...
                }
            });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-29
      • 1970-01-01
      • 2011-03-10
      • 2014-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多