Windows Phone - 将 TextBox 或其他控件绑定到按钮的 CommandParameter

Posted

技术标签:

【中文标题】Windows Phone - 将 TextBox 或其他控件绑定到按钮的 CommandParameter【英文标题】:Windows Phone - Binding TextBox or other control to CommandParameter of Button 【发布时间】:2014-07-05 10:14:37 【问题描述】:

我正在迈出在我的 Windows Phone 应用程序中使用命令(通过实现ICommand 接口)的第一步。现在我遇到了一个我似乎无法弄清楚的问题。我正在将一个控件(在本例中是一个文本框)绑定到 ButtonCommandParameter 属性:

<Button x:Name="BTN_Search"
        Style="StaticResource ButtonNoPressedStyle"
        BorderThickness="0"
        ccontrols:TiltEffect.IsTiltEnabled="True"
        Grid.Column="1"
        Height="85"
        Margin="0,0,0,-2"
        CommandParameter="Binding ElementName=TB_Search"
        Command="Binding SearchTermCommand">
        <Button.Background>
            <ImageBrush ImageSource="/Assets/Images/searchbtn.png" />
        </Button.Background>
</Button>

当应用程序启动并实例化视图模型时,CanExecute 方法会连续触发两次。

public override bool CanExecute(object parameter)
    
        if (parameter != null)
        
            var textbox = parameter as TextBox;
            if ((textbox.DataContext as MainPageViewmodel).SearchTerm == null)
            
                (textbox.DataContext as MainPageViewmodel).SearchTerm = "";
                return true;
            
            else if (String.IsNullOrWhiteSpace(textbox.Text)) return false;
            else if (textbox.Text.Any(Char.IsDigit)) return false;
            else if (textbox.Text.Length < 4) return false;
            else if (_commandExecuting) return false;
            else
            
                var bindingExpression = textbox.GetBindingExpression(TextBox.TextProperty);
                bindingExpression.UpdateSource();
                return true;
            
        
        return true;
    

第一次参数是null,第二次它包含文本框。由于这种行为,我必须让前两次,CanExecute 方法返回 true,否则按钮将被禁用。

我已经阅读了一些可能与RaiseCanExecuteChanged() 有关的其他主题,但我也不太确定。 这个question 有一些关于这个问题的答案,但这些答案不符合我的需要,因为大多数解决方案都是针对 WPF(使用 CommandManagerIMultiValueConverter)而其他的似乎不起作用。

是否有任何解决方案可以确保CanExecute 只触发一次,或者这种行为的解释是什么?

【问题讨论】:

在“CanExecute”的测试中更新绑定表达式似乎是在滥用 ICommand 模式。为什么需要这样做? 因为我有这样的想法,即仅在需要时(满足所有要求时)进行更新。在研究了这个之后,我想我可以将 INotifyPropertyChanged 添加到有问题的属性中。感谢您引起我的注意。但我仍然想知道为什么会这样。 我不知道究竟是为什么,但这个猜测对我来说是有道理的:第一次检查是什么时候第一次构造命令对象;第二个检查是绑定 CommandParameter 时(即加载 TB_Search 元素)。 这意味着每个与命令绑定的控件或属性在加载或更新时触发 RaiseCanExecuteChanged()? 好问题,我真的不知道...根据经验,通过 NotifyPropertyChanged 触发它的属性更改。依赖属性改变?视觉树的变化?不知道... 【参考方案1】:

我认为当命令参数第一次有界时,您的文本框未初始化。尝试使用双向模式绑定文本框和viewmodel参数(参数必须是DependencyProperty或者你的viewmodel必须实现INotifyPropertyChanged接口)然后将此参数传递给命令参数。

【讨论】:

【参考方案2】:

这个答案没有提供任何明确的结论,但是在我测试了CommandParameter 上的各种绑定并查看了微软为 ICommand 接口提供的information 和相关的CanExecuteChanged 事件之后,我不得不得出结论,这与 McGarnagle 已经提出的以下任何一项有关:

视觉树的变化。 对依赖属性/对象的更改。

这是有道理的,因为文档说以下内容:“发生影响命令是否应执行的更改时发生。”

我注意到了什么:

当绑定 Viewmodel 的任何属性时,CanExecute 只会在启动时触发一次。参数为null。 当绑定任何其他元素此元素的属性时,CanExecute 在启动时被触发两次。参数第一次为null,第二次包含指定元素的元素或属性。 当绑定 Button 本身 Binding RelativeSource=RelativeSource Mode=Self 时,CanExecute 在启动时被触发一次,并且参数包含 Button 元素。

正如我之前所说,这并不能回答任何问题,但我认为提供一些有关此问题的额外信息不会有什么坏处。如果有人找到明确的答案,并提供这种行为的原因,我当然会感激不尽。

无论如何,我在自己的应用程序中使用了第一个场景并重新构建了逻辑,所以现在它可以按照我最初的预期工作。

【讨论】:

以上是关于Windows Phone - 将 TextBox 或其他控件绑定到按钮的 CommandParameter的主要内容,如果未能解决你的问题,请参考以下文章

windows phone 中 textBox1_TextChanged 的​​性能变慢

Windows Phone 8 滚动文本框的内容

找出 Windows Phone 中系统定义样式的内部结构

占位符文本框 Windows Phone 8

计算点击次数并显示在另一个页面上[Windows Phone c#]

是否可以将 Windows Phone App 项目转换为 Windows Phone 类库?