Wpf 如何将ViewModel中的命令绑定到Behavior中的命令?

Wpf 如何将ViewModel中的命令绑定到Behavior中的命令?,wpf,mvvm,prism-7,Wpf,Mvvm,Prism 7,WPF项目+Prism 7+纯MVVM模式 <Button Command="{Binding ClearCommand}"/> <TextBox Text="{Binding File}"> <i:Interaction.Behaviors> <local:ClearTextBehavior ClearTextCommand="{Binding ClearCommand, Mode=OneWayToSource}" />

WPF项目+Prism 7+纯MVVM模式

<Button Command="{Binding ClearCommand}"/>
<TextBox Text="{Binding File}">
    <i:Interaction.Behaviors>
        <local:ClearTextBehavior ClearTextCommand="{Binding ClearCommand, Mode=OneWayToSource}" />
    </i:Interaction.Behaviors>
</TextBox>
很简单,我有一个文本框,当按下某个按钮时需要清除它,而不违反MVVM模式

<Button Command="{Binding ClearCommand}"/>
<TextBox Text="{Binding File}">
    <i:Interaction.Behaviors>
        <local:ClearTextBehavior ClearTextCommand="{Binding ClearCommand, Mode=OneWayToSource}" />
    </i:Interaction.Behaviors>
</TextBox>
行为

问题是ViewModel中的命令总是空的,它没有绑定到Behavior中的命令,尽管我确保它是在Behavior类中初始化的


注意:请不要建议将文件属性设置为空字符串,因为这只是一个示例,在我的实际情况中,我需要选择所有文本,因此如果我正确理解您的问题,我确实需要访问行为的关联对象,您想知道为什么ViewModel中的ICommand没有设置为行为中定义的DelegateCommand

问题是,ICommand和DelegateCommand没有直接连接。我想您可能误解了绑定是如何工作的,以及使用这些绑定会发生什么

首先,ICommand来自一个类,因此是一个引用类型

其次,对ICommand的引用保存在DependencyProperty ClearTextCommandProperty中

第三,通过在XAML中使用绑定,类似这样的情况会发生在C代码中:

Binding binding = new Binding();
binding.Path = new PropertyPath("ClearTextCommand");
binding.Source = ClearCommand; 
BindingOperations.SetBinding(TextBox.ClearTextCommandProperty, binding);
现在重要的是:我不知道哪一个赋值首先出现,但这两行都将覆盖ClearTextCommandProperty中的值引用

在任何情况下都不会有这样的任务:

ViewModel.ClearCommand = SomeICommand;
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

<Button>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <utils:SelectAllText TargetName="TextToSelect"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

<TextBox x:Name="TextToSelect" Text="{Binding File}"/>
因此,正如@Andy提到的,它是空的

编辑以匹配“选择所有文本”

此外,我建议您放下这些复杂的东西,像这样充分利用互动软件包的潜力:

ViewModel.ClearCommand = SomeICommand;
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

<Button>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <utils:SelectAllText TargetName="TextToSelect"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

<TextBox x:Name="TextToSelect" Text="{Binding File}"/>

如果您在此处查看此示例: 您会注意到我在那里有一个ICommand,它被设置为运行一个方法

如果它只是一个具有Get和Set的ICommand,那么它将为NULL。有一个属性,但在设置为某个值之前它是空的

这是一种非常笨拙的实现ICommand的方法,但不依赖外部库或任何东西

如果您看一下该系列的第二篇文章,它使用mvvmlight和relaycommand,因此创建命令就不那么麻烦了

如果您查看该代码,AddListCommand最初为null。 它在构造函数中被设置为一个新的RelayCommand,这意味着它不为null

这相当简单,但命令的代码与属性位于不同的位置,因此通常采用更优雅的方法。如图所示:

说了这么多。 选择所有文本是在视图中执行的操作,而不是在viewmodel中。 您不应该真的将UI从视图传递到viewmodel中


与其说是命令,还不如说你应该绑定一个在viewmodel中设置并在行为中执行的bool。

ClearCommand在你的viewmodel中为空。@Andy是的,我不知道为什么,它应该是行为的绑定,但这不是你想解决SelectAllText问题还是你认为可以解决SelectAllText问题的这个命令问题?@SirRufo主要问题是SelectAllText,我想解决这个问题,那么你应该重写你的问题:如何。。。选择全部文本?我试过。。。但是没有成功。
public class SelectAllText : TargetedTriggerAction<TextBox>
{
    protected override void Invoke(object parameter)
    {
        if (Target == null) return;

        Target.SelectAll();
        Target.Focus();
    }
}
public RelayCommand AddListCommand { get; set; }

public MainWindowViewModel()
{
    AddListCommand = new RelayCommand(AddList);
}
private void AddList()
{
    stringList.Add(myString));
}