WPF MVVM绑定超链接RequestNavigate到View模型

时间:2016-03-08 10:01:35

标签: c# wpf xaml mvvm hyperlink

在WPF表单上,我有一个超链接,点击后可以在重定向到内部网页之前聚合数据库中的一些数据。

目前XAML看起来如下:

<Hyperlink RequestNavigate="Hyperlink_RequestNavigate" IsEnabled="{Binding CanTakePayment}">
  Launch Payments Portal
</Hyperlink>

使用db stuff Hyperlink_RequestNavigate方法,它位于View.xaml.cs

它看起来像:

private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
    var transactionReference = GetToken(100M, "13215", "product");
    var url = string.Format("{0}New?transactionReference={1}", Settings.Default.PaymentUrlWebsite, transactionReference);
    e.Handled = true;
}

我不喜欢这种机制在这里,而是希望将其移动到View模型。

我尝试做的是添加到ViewModel属性

public ICommand NavigateToTakePayment       
{
    get { return _navigateToTakePayment; }
    set { _navigateToTakePayment = value; }
}

并在XAML中将绑定更改为

<Hyperlink RequestNavigate="{Binding Path=NavigateToTakePayment}" IsEnabled="{Binding CanTakePayment}"> 
   Launch Payments Portal
</Hyperlink>

但它开始给我施放例外。

将此机制从View移至ViewModel的最佳方法是什么?

3 个答案:

答案 0 :(得分:3)

您的应用问题是ICommand在使用前未初始化 我有一个这样的Command实现:

public class RelayCommand : ICommand
    {
        Predicate<object> _canExecute;
        Action<object> _execute;
        bool _defaultBehaviourForCanExecute;

        public RelayCommand(Action<object> execute, bool defaultBehaviourForCanExecute = true, Predicate<object> canExecute = null)
        {
            _canExecute = canExecute;
            _execute = execute;
            _defaultBehaviourForCanExecute = defaultBehaviourForCanExecute;
        }

        public bool CanExecute(object parameter)
        {
            if (_canExecute != null)
            {
                Logger.LogInformation("Evaluating can execute method for " + _canExecute.Method.DeclaringType + "->"+_canExecute.Method.Name);
                return _canExecute.Invoke(parameter);
            }
            return _defaultBehaviourForCanExecute;
        }

        public event EventHandler CanExecuteChanged;

        public void RaiseCanExecuteChanged()
        {
            if (CanExecuteChanged != null)
                CanExecuteChanged(this, new EventArgs());
        }

        public void Execute(object parameter)
        {
            Logger.LogInformation("Executing command method for " + _execute.Method.DeclaringType + "->" + _execute.Method.Name);
            _execute.Invoke(parameter);
            RaiseCanExecuteChanged();
        }
    }  

现在我的ViewModel正在初始化,如此:

NavigateToTakePayment = new RelayCommand(navigateToTakePayment CommandMethod);//it also can take canExecute method if you need a condition before executing.  

然后在你的xaml中你就像这样使用它:

<Hyperlink RequestNavigate="{Binding Path=NavigateToTakePayment}" IsEnabled="{Binding CanTakePayment}">
    Launch Payments Portal
</Hyperlink>

BTW:当您需要禁用超链接时,请实施canexecute方法 然后它会自动完成。如果您需要更多信息,我会更新我的答案 快乐的编码

答案 1 :(得分:1)

HyperLink有点问题。它不支持命令绑定。

可以通过附加的属性来实现对命令绑定的支持,但是只需修改按钮即可执行相同的操作。

<Style TargetType="Button" x:Key="HyperlinkStyledButton">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="Button">
        <TextBlock Foreground="DodgerBlueColor"
                   Text="{TemplateBinding Content}"
                   TextDecorations="Underline" 
                   Cursor="Hand" />
    </ControlTemplate>
  </Setter.Value>
</Setter>

然后使用超链接:

<Button Command="{Binding OpenHttpLinkCommand}" Content="www.google.com" 
        Style="{StaticResource HyperlinkStyledButton}" ToolTip="Some custom tooltip"/>

假设标准MVVM绑定正常工作:

在ViewModel中:

public ICommand OpenHttpLinkCommand { get; }

在ViewModel构造函数中:

this.OpenHttpLinkCommand = new DelegateCommand(this.OnOpenHttpLinkCommand);

打开带有链接的浏览器的命令:

private void OnOpenHttpLinkCommand()
{
    try
    {
        System.Diagnostics.Process.Start("http://www.google.com/");
    }
    catch (Exception)
    {
        // TODO: Error.
    }
}

答案 2 :(得分:0)

旧线程,但对于像我一样仍然遇到它的人来说,Hyperlink 确实支持 ICommandBinding,但是您需要一个派生类来这样做:

using System.Windows.Documents;

public class HyperlinkCommander : Hyperlink
{
    protected override void OnClick()
    {
        Command.Execute(null);
    }
}

然后在您的 xaml 中使用它,就像在您的 ViewModel 中将 Button 绑定到您的 ICommand 时一样使用它,在本例中称为 HyperlinkClickerCommand。像这样:

<localControls:HyperlinkCommander Command="{Binding HyperlinkClickerCommand}" >
    Click me!
</localControls:HyperlinkCommander>

在你的 xaml 顶部附近有这样的东西:

<Window
    ... 
    xmlns:localControls="clr-namespace:TestProject.Controls"
    ...
>

其中 HyperlinkClickerCommand 是您要绑定到的 ViewModel 中的命令。上面的超链接将触发绑定命令的Execute,并遵守它的CanExecute