如何使用 Caliburn Micro 附加 GridViewColumnHeader.Click 的事件处理程序?

How do I attach an eventHandler for GridViewColumnHeader.Click with Caliburn Micro?

我有一个 ListView 和一个 GridView 作为视图,它按照约定绑定到我的 ViewModel 的 Instances 属性:

<ListView Name="Instances">
  <ListView.View>
    <GridView>
      <GridViewColumn DisplayMemberBinding="{Binding Property}"
                      Header="Property"/>
    </GridView>
  </ListView.View>
</ListView>

现在我需要在单击 GridViewColumnHeader 时在 ViewModel 上触发一些方法。

我试过像这样增强 GridViewColumn

<ListView Name="Instances"
          cal:Message.Attach="[Event GridViewColumnHeader.Click] = [Action Foo()]">
  <!-- the rest stays unchanged -->
</ListView>

我什至试过像这样使用 ColumnHeaderContainerStyle

<GridView>
  <GridView.ColumnHeaderContainerStyle>
    <Style TargetType="GridViewColumnHeader">
      <EventSetter Event="Click">
        <cal:ActionMessage MethodName="Foo"/>
        <!-- does not compile -->
      </EventSetter>
    </Style>
  </GridView.ColumnHeaderContainerStyle>
</GridView>

这显然行不通。

如何使用 Caliburn Micro 将 ViewModel 的方法(而不是带有绑定的命令)连接到附加事件(以更通用的方式询问)?

我已经按照@XAMIMAX 的建议解决了这个问题:

<GridView.ColumnHeaderTemplate>
  <DataTemplate>
    <Button Content="{Binding}"
            BorderBrush="Transparent"
            Background="Transparent"
            cal:Message.Attach="[Event Click] = [Action Foo($this)]">
      <Button.Template>
        <ControlTemplate TargetType="Button">
          <ContentPresenter />
        </ControlTemplate>
      </Button.Template>
    </Button>
  </DataTemplate>
</GridView.ColumnHeaderTemplate>

这会在 ViewModel 上触发 Foo,然后将 {Binding}(在我的例子中是:属性-名称)传递给它。

我找到了 this 一篇解释了 calibrum 的文章,我以前从未使用过 calibrum,所以我不得不做一些研究。
这是文章如何以另一种方式呈现 Binding

<TextBox x:Name="Name" />
<Button Content="Save"> 
    <i:Interaction.Triggers> 
        <i:EventTrigger EventName="Click"> 
            <cal:ActionMessage MethodName="Save"> 
               <cal:Parameter Value="{Binding ElementName=Name, Path=Text}" /> 
            </cal:ActionMessage> 
        </i:EventTrigger> 
    </i:Interaction.Triggers> 
</Button> 

其中:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
xmlns:cal="http://www.caliburnproject.org"

为了让您在应用程序中继续使用 TextBlock,您必须像这样创建 GridViewColumnHeader 的显式定义:

<DataTemplate>
<!-- Without the Calibrum micro -->
    <TextBlock Text="Test">
       <TextBlock.InputBindings>
          <MouseBinding MouseAction="LeftClick" Command="{Binding TestCommand}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=TextBlock}, Path=Text}"/>
       </TextBlock.InputBindings>
    </TextBlock>
<!-- With Calibrum Micro -->
    <TextBlock>
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="LeftClick">
                <cal:ActionMessage MethodName="Save">
                    <cal:Parameter Value="{Binding ElementName=Name, Path=Text}" /> 
                </cal:ActionMessage> 
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </TextBlock>
</DataTemplate>

现在这只是基于我从互联网上收集到的material,我无法在工作中对其进行测试。
然而,如果这不起作用,应该会让您了解如何克服开发中的一些困难。
编辑:
并回答你的问题:
GridViewColumnHeader Template 替换为 DataTemplate 的显式定义并使用按钮以便您可以附加到 Click 事件,或者您可以使用 TextBlock 就像避免使用 Button.
带来的不必要开销的示例 编辑
在做了一些研究之后,我可以得出结论,在您的视图模型上使用这些方法既简单又有趣 :-)。
看看我的工作 ListView:

<ListView>
<ListView.View>
    <GridView>
        <GridView.ColumnHeaderTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding}">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="MouseDown">
                            <ei:CallMethodAction MethodName="TestPublicMethod" TargetObject="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext}"/>
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </TextBlock>
            </DataTemplate>
        </GridView.ColumnHeaderTemplate>
        <GridViewColumn Header="Example Header"/>
    </GridView>
</ListView.View>
<ListViewItem>
    <StackPanel Orientation="Horizontal">
        <TextBlock>
            normal text with a lot of characters
        </TextBlock>
        <Rectangle Width="20" Height="20" Fill="Red"/>
    </StackPanel>
</ListViewItem>

和视图模型(消息是带有 INPC 的 属性):

#region Public Methods

public void TestPublicMethod() { Message = "You have just invoked a public method !!!."; }

#endregion
其中:

xmlns:ei="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"  

抱歉格式不佳,但编辑不想在星期一早上工作:-p。
因为 TextBlock 将仅使用所需的最小值 space,所以您可以使用这个肮脏的技巧让它拉伸到列 Header 的宽度:

Width="{Binding RelativeSource={RelativeSource AncestorType=GridViewColumnHeader}, Path=ActualWidth}"