如何使用 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}"
我有一个 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}"