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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35864275/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 13:42:16  来源:igfitidea点击:

WPF MVVM bind Hyperlink RequestNavigate to View model

c#wpfxamlmvvmhyperlink

提问by Matas Vaitkevicius

On WPF form I have a hyperlink that when clicked is supposed aggregate some data in database before redirecting to internal web page.

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

Currently XAML looks following:

目前 XAML 看起来如下:

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

to do the db stuff Hyperlink_RequestNavigatemethod is used, that resides in View.xaml.cs

使用db stuffHyperlink_RequestNavigate方法来做,驻留在View.xaml.cs

It looks something like:

它看起来像:

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;
}

I don't like this mechanism being here and would prefer to move it to View model.

我不喜欢这里的这种机制,更愿意将其移至 View 模型。

What I tried to do is add to ViewModel property

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

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

and in XAML change binding to

并在 XAML 中将绑定更改为

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

but it started giving me cast exceptions.

但它开始给我投射异常。

What is most appropriate way to move this mechanism from View to ViewModel?

将此机制从 View 移动到 ViewModel 的最合适方法是什么?

采纳答案by XAMlMAX

Problem with your app is that the ICommandis not initialized before use.
I have a Command implementation like so:

您的应用程序的问题ICommand是在使用前未初始化。
我有一个像这样的命令实现:

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();
        }
    }  

Now this is being initialized in my ViewModellike so:

现在这正在ViewModel像这样被初始化:

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

then in your xaml you use it like this:

然后在您的 xaml 中,您可以像这样使用它:

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

BTW: when you Hyperlink needs to be disabled implement a canexecutemethod
and then it will be done automatically. If you need more info I will update my answer.
Happy coding

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

回答by Contango

HyperLinkis a bit of a problem child. It does not support command binding.

HyperLink是个有点问题的孩子。它不支持命令绑定。

It's possible to shoehorn support for command binding into it with an attached property, but it's easier to just modify a button to do the same thing.

可以通过附加属性将命令绑定的支持硬塞到其中,但仅修改按钮来执行相同的操作会更容易。

<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>

Then use the hyperlink:

然后使用超链接:

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

Assuming that standard MVVM binding is working correctly:

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

In the ViewModel:

在视图模型中:

public ICommand OpenHttpLinkCommand { get; }

In the ViewModel constructor:

在 ViewModel 构造函数中:

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

And the command to open the browser with a link:

以及使用链接打开浏览器的命令:

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