0

WPF 项目 + Prism 7 +(纯 MVVM 模式)

TextBox很简单,当按下某个按钮时,我需要清除哪些(不违反 MVVM 模式)

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

视图模型

public class ViewModel {
    public ICommand ClearCommand { get; set; }
}

行为

public class ClearTextBehavior : Behavior<TextBox>
{
    public ICommand ClearTextCommand
    {
        get { return (ICommand)GetValue(ClearTextCommandProperty); }
        set
        {
            SetValue(ClearTextCommandProperty, value);
            RaisePropertyChanged(); 
        }
    }

    public static readonly DependencyProperty ClearTextCommandProperty =
        DependencyProperty.Register(nameof(ClearTextCommand), typeof(ICommand), typeof(ClearTextBehavior));

    public ClearTextBehavior()
    {
        ClearTextCommand = new DelegateCommand(ClearTextCommandExecuted);
    }

    private void ClearTextCommandExecuted()
    {
        this.AssociatedObject.Clear();
    }
}

问题是 ViewModel 中的命令始终为空(它没有绑定到 Behavior 中的命令),尽管我确保它是在行为类中初始化的。

注意:请不要建议将 File 属性设置为空字符串,因为这只是一个示例,在我的实际情况中,我需要选择所有文本,所以我真的需要访问AssociatedObject行为

4

2 回答 2

1

如果我正确理解了您的问题,您想知道为什么ICommandinViewModel未设置DelegateCommandBehaviour.

问题是,ICommandDelegateCommand没有直接联系。我假设您可能误解了 a 的Binding工作原理以及使用它们会发生什么。

首先,ICommand“来自”a Class,因此是引用类型。

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

第三,通过在C# 代码中使用类似这样Binding的东西:XAML

Binding binding = new Binding();
binding.Path = new PropertyPath("ClearTextCommand");
binding.Source = ClearCommand; 
BindingOperations.SetBinding(TextBox.ClearTextCommandProperty, binding);

现在重要的是:我不确切知道哪个分配首先出现,但是这两行都会Value覆盖ClearTextCommandProperty!

//either here
SetBinding(TextBox.ClearTextCommandProperty, binding);

//or here 
ClearTextCommand = new DelegateCommand(ClearTextCommandExecuted);
//Which could be written as
SetValue(ClearTextCommandProperty, new DelegateCommand(ClearTextCommandExecuted));

在任何时候都没有这样的任务:

ViewModel.ClearCommand = SomeICommand;

因此Null,正如@Andy 提到的那样


编辑以匹配选择所有文本

此外,我建议你放弃这些复杂的东西,并Interactivity像这样使用包的全部潜力:

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}"/>

SelectAllText

public class SelectAllText : TargetedTriggerAction<TextBox>
{
    protected override void Invoke(object parameter)
    {
        if (Target == null) return;

        Target.SelectAll();
        Target.Focus();
    }
}
于 2018-11-21T10:31:51.997 回答
0

如果您在此处查看此示例: https ://social.technet.microsoft.com/wiki/contents/articles/31915.wpf-mvvm-step-by-step-1.aspx 您会注意到我有一个ICommand 在那里,它被设置为运行一个方法。

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

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

如果您看一下该系列的第二篇文章,它使用 mvvmlight 和 relaycommand,因此创建命令相当简单。

https://social.technet.microsoft.com/wiki/contents/articles/32164.wpf-mvvm-step-by-step-2.aspx

public RelayCommand AddListCommand { get; set; }

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

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

这相当简单,但命令的代码与属性位于不同的位置,因此通常采用更优雅的方法。如此处所示:https ://msdn.microsoft.com/en-gb/magazine/dn237302.aspx


说了这么多。选择所有文本是在视图中做的,而不是视图模型。您不应该将视图中的一段 UI 传递到视图模型中。

您应该绑定一个在视图模型中设置并在行为中起作用的布尔值,而不是一个命令。

于 2018-11-21T13:40:10.767 回答