【问题标题】:How to bind control property?如何绑定控件属性?
【发布时间】:2012-11-11 23:45:06
【问题描述】:

我正在使用 Caliburn.Micro 的基于约定的绑定,但我有一个小问题:

如何设置绑定应绑定到的属性?如果我使用x:Name="SomeProperty" 创建一个控件,我该如何选择是否应该将SomeProperty 的值绑定到我的控件的Value 属性、我的控件的OnClick 事件或其他不同的东西,例如@987654325 @ 或 Tag 属性?

示例:我有这个HyperlinkButton,我想绑定到一个特定的 URL,我想将OnClick 绑定到我的 ViewModel 中的一个事件处理程序。

<HyperlinkButton x:Name="BookDetailsViewModel_InfoLink" Content="Read more" />

但是,Content 属性不是用Read more 填充的,而是用 URL 的值填充的。在这个例子中,我该如何:

  • 将导航 URI 设置为我的 ViewModel 属性中 URL 的值
  • 将内容设置为“阅读更多”
  • 在我的 ViewModel 中指定一个处理点击的事件处理程序

谁能帮帮我?

【问题讨论】:

  • 您是说要自定义此控件的约定以便它执行您想要的操作,或者您只是在使用或不使用约定的情况下无法正常工作?我的假设是您希望约定为您完成这一切
  • 我只是想让它工作,我真的不在乎它是否适用于约定。一些显式绑定代码对我来说很好,但是当我使用 {Binding SomeProperty} 时它不起作用。
  • 添加了关于如何基于约定和显式执行此操作的说明。让我知道这是否有帮助

标签: data-binding mvvm windows-runtime caliburn.micro caliburn


【解决方案1】:

您可以在 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 方法。

【讨论】:

  • 我尝试了显式解决方案,它到达了我的视图模型的事件处理程序,但参数为空。我的方法如下所示:public void HyperlinkClicked(EventArgs args) 我是否在这里传递了错误类型的参数?我不知道它应该接受哪种类型的论据(一个人怎么知道这些事情?)。
  • CM 不使用EventArgs - 它使用属性的类型。如果您进入代码隐藏并声明一个 HyperlinkBut​​ton 并查看 NavigateURI 属性是什么类型(可能是字符串?还是 URI?)并将其用作参数类型。如果有疑问,请将方法上的类型设置为object 并对其进行断点 - 请参阅参数由 CM 传递的类型。 CM 会将 null 传递给它无法与提供的参数匹配的参数,因此它不应该抛出异常,但无论如何它都会调用该方法。我的猜测是public void HyperlinkClicked(string uri) 会起作用。 (好吧,我撒谎了,文档说它的 System.Uri)
  • 嗯,我的超链接绑定到一个字符串,但我得到null 偶数时间,即使我将参数设置为一个对象。这是我的 XAML:&lt;HyperlinkButton Content="Open in web browser" NavigateUri="{Binding BookDetailsViewModel_PreviewLink}" cal:Message.Attach="[Event Click] = [Action HyperlinkClicked($this.NavigateURI)]" /&gt;
  • NavigateUri - URI 上的大写字母应该是 Uri 我的错。属性解析器区分大小写,因为 c# 区分大小写。就像我说的,你最好使用约定,因为它可以帮助避免这些小错误,因为在设计时没有任何东西会检查这个。哦,是的,仅仅因为 NavigateUri 绑定到一个字符串,并不意味着该属性将是字符串 - 在 WPF/RT/SL 中有称为 TypeConverters 的东西将传入的值转换为所需的类型,所以NavigateUri 的转换器解析绑定的字符串并将其转换为System.Uri
  • 这里有一些关于TypeConverters 的有用信息,以防你决定编写自己的控件,甚至UserControl...msdn.microsoft.com/en-us/library/aa970913.aspx - 当你想为你的通过 XAML 标记自定义控件
猜你喜欢
  • 2013-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多