您可以在 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 上的方法和属性,因为您不能拥有共享相同名称的方法和属性,但我确信 CM 会冒泡如果您在 VM 上没有适当的方法,则将操作消息向上传递到 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
方法。