在WPF和MVVM中,如何为<Hyperlink>添加“复制”上下文菜单?

3

在大多数现代Web浏览器中,用户可以右键单击超链接并使用“复制链接地址...”上下文菜单。

在WPF中,我想知道是否有一种方法可以将相同的功能添加到<Hyperlink> XAML标记中?

我正在使用MVVM Light。


当然。给它添加一个上下文菜单。如果你在操作时遇到问题,可以回来进行编辑。 - user1228
请查看http://www.codeproject.com/Articles/162784/WPF-ContextMenu-Strikes-Again-DataContext-Not-Upda。 - Contango
2个回答

5

实际上,这比应该的要困难得多。

原因在于ContextMenu不是可视树的一部分,这意味着尝试使用任何最合适的绑定都会返回null而不是预期值。

解决方案是将整个超链接包装在一个UserControl中,然后使用{Binding PlacementTarget.Content}来访问我们想要的属性。在这种情况下,所需属性是URL,我们需要它作为参数,当我们想通过上下文菜单将超链接复制到剪贴板时。当然,我们可以指定URL两次,但这违反了DRY(不要重复自己)原则。

我正在使用MVVM Light

XAML

第二个Command Parameter的意图是绑定到父级Hyperlink标记中的NavigateUri的内容,并将其作为上下文菜单的参数传递,以便可以将其复制到剪贴板上。

<UserControl>
    <Hyperlink NavigateUri="http://www.google.com/" 
               Command="{Binding OnClickHyperlink}"
               CommandParameter="{Binding NavigateUri, RelativeSource={RelativeSource Self}}">
        www.google.com
        <Hyperlink.ContextMenu>
            <ContextMenu>
                <MenuItem Header="Copy link address" 
                          Command="{Binding OnCopyHyperlink}"                                                  
                          CommandParameter="{Binding PlacementTarget.Content.NavigateUri, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}">
                </MenuItem>
            </ContextMenu>
        </Hyperlink.ContextMenu>
    </Hyperlink>
</UserControl>

C#处理超链接点击事件

private ICommand _onClickHyperlink;
public ICommand OnClickHyperlink
{
    get
    {
        return _onClickHyperlink ?? (_onClickHyperlink = new RelayCommand<Uri>(
            hyperlink =>
            {
                // Handle Hyperlink click here using Process.Start().
            }));
    }
}

C#用于复制超链接

private ICommand _onCopyHyperlink;
public ICommand OnCopyHyperlink
{
    get
    {
        return _onCopyHyperlink ?? (_onCopyHyperlink = new RelayCommand<Uri>(
            hyperlink =>
            {
                Clipboard.SetText(hyperlink.OriginalString);
            }));
    }
}

1
我发现在创建自定义日志窗口控件时,以下方法非常有用。它会检查鼠标是否悬停在超链接对象内的文本运行上。
private void LogWindow_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
   var hyperlink = (Mouse.DirectlyOver as Run)?.Parent as Hyperlink;
   if(hyperlink != null)
   {
       //do whatever you want with the link now
       //e.g. set the command param on a named menu item  
       MenuItem item = this.UriCopyMenuItem;
       item.CommandParameter = hyperlink.NavigateUri;
       item.Visibility = Visibility.Visible;
       ...
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接