您可以在 CM 中为每个元素类型自定义 ConventionManager。默认的开箱即用实现应用于任何没有显式自定义的元素
要添加新约定,您只需调用 ConventionManager.AddElementConvention
方法如下(来自 CM 源码)
/// <summary>
/// Adds an element convention.
/// </summary>
/// <typeparam name="T">The type of element.</typeparam>
/// <param name="bindableProperty">The default property for binding conventions.</param>
/// <param name="parameterProperty">The default property for action parameters.</param>
/// <param name="eventName">The default event to trigger actions.</param>
public static ElementConvention AddElementConvention<T>(DependencyProperty bindableProperty, string parameterProperty, string eventName)
{
return AddElementConvention(new ElementConvention
{
ElementType = typeof(T),
GetBindableProperty = element => bindableProperty,
ParameterProperty = parameterProperty,
CreateTrigger = () => new EventTrigger { EventName = eventName }
});
}
如您所见,它需要一些参数 - 您需要为绑定、操作和触发器传递默认属性,例如
ConventionManager.AddElementConvention<HyperlinkButton>(HyperlinkButton.NavigateUri, "NavigateUri", "Click");
(假设点击事件称为Click)
由于您不再绑定 Content 属性(因为约定现在绑定 NavigateUri),您可以保持原样,它应该保持“阅读更多...”
所以现在你有一个HyperlinkButton 控件,它应该按照约定绑定到NavigateUri,并在Click 事件被触发时调用共享它的名称的方法。
编辑:
我可能会澄清一下,我认为您不能在同一 VM 上同时绑定 方法和属性,因为您不能同时拥有一个方法和属性共享相同的名称,但我确信如果您在 VM 上没有适当的方法,CM 会将操作消息冒泡到 VM 层次结构中……但没有尝试过。要绑定动作,请参阅下面我的其他编辑
别忘了,您总是可以使用显式语法来完成所有这些操作!
<HyperlinkButton Content="Read more..." NavigationURI="{Binding SomeUri}" cal:Message.Attach="[Event Click] = [Action HyperlinkClicked($this.NavigateUri)" />
但走惯例路线可能会更好:)
编辑:
可能会添加如何获取约定以从超链接中获取属性值 -
<HyperlinkButton x:Name="SomeLink" Content="Read more..." cal:Message.Attach="HyperlinkClicked(SomeLink)" />
CM 知道,由于您将NavigateUri 设置为默认操作参数,它应该抓住它并将其传递给您在操作绑定中指定的方法。我想知道$this 是否也可以工作(你可能需要$this.NavigateUri)。您可以跨控件执行此操作,例如
<TextBox x:Name="SomeTextBox" />
<HyperlinkButton x:Name="SomeLink" Content="Read more..." cal:Message.Attach="HyperlinkClicked(SomeTextBox)" />
默认情况下,上面会将文本框的Text 属性传递给HyperlinkClicked 方法。