【问题标题】:WPF Prism Bound field value not available until command firedWPF Prism Bound 字段值在命令触发之前不可用
【发布时间】:2013-10-03 15:47:14
【问题描述】:

我已经在我的桌面 WPF 非银光应用程序中实现了 prism MVVM 模式。在屏幕加载期间,我正在用一组值填充一个列表框。此列表框绑定到 ViewModel(这是我的 DataContext),并且每个项目都使用 DataTemplate 呈现。这工作正常。然后,我尝试创建一个文本框,允许用户在输入时过滤显示哪些记录。我的自然想法是跟踪 KeyUp 或 TextChanged 事件,但事实证明,如果尝试按照建议保持对 ICommand 的使用,这比绑定到事件更困难。我找不到解决这个问题的简单方法,也不想再花时间解决这个问题,因为我的最后期限快到了。考虑到这一点,我尝试了以下解决方案:

XAML:

<TextBox Name="ChannelSearch" Text="{Binding Path=ChannelFilter, Mode=TwoWay}"  TextChanged="ChannelSearch_TextChanged" />

代码隐藏:

private void ChannelSearch_TextChanged(object sender, TextChangedEventArgs e) {
        var vm = ((IExpressionEditorViewViewModel)ViewModel);
        if (vm.FilterChannels.CanExecute())
            vm.FilterChannels.Execute();
    }

视图模型:

 //In the constructor:
 FilterChannels = new DelegateCommand(doFilterChannels, doCanFilterChannels);

 //Class properties:
 public string ChannelFilter { get; set; }

 //Methods used by DelegateCommand:
 private void doFilterChannels(){
        if (string.IsNullOrWhiteSpace(ChannelFilter))
            this.IdFileRows = _allIdFileRows;
        else{
            var lower = ChannelFilter.Trim().ToLower();

            this.IdFileRows = _allIdFileRows.Where(
                r => (DisplayChannel && r.A_RowChannelNum.ToLower().Contains(lower))
                    || (DisplayMnemonic && r.B_Mnemonic.ToLower().Contains(lower))
                    || (DisplayDescription && r.F_Description.ToLower().Contains(lower))
                ).ToList();
        }
    }

 private bool doCanFilterChannels() {

        return true;
    }

所有这些都准备就绪后,我开始调试。 KeyUp 和 TextChanged 的​​结果没有区别。当“doFilterChannels”被点击时,ChannelFilter 文本每次都是空的。开始让我难以置信的是,如果我点击屏幕上的保存按钮,它会直接点击 DelegateCommand,如下所示:

<Button Content="Save" Command="{Binding Path=SaveExpression}"></Button>

SaveExpression = new DelegateCommand(doSaveExpression, doCanSaveExpression);

      private void doSaveExpression() {
        Result result = new Result();
        try {

            result.Success = true;
        }
        catch (Exception e) {
            result.ResultMessages.Add(new ResultMessage { ErrorCode = "500", Message = e.ToString() });
        }

        result.ThrowErrors();
    }
    private bool doCanSaveExpression() {
        return true; //TODO validation
    }

当我打破 doSaveExpression 方法并检查 ChannelFilter 时,值在那里并且准确。为什么会在此处发生,而不是在触发 KeyUp/TextChanged 事件时发生?有没有更好的方法来处理这些情况?

【问题讨论】:

    标签: c# wpf xaml mvvm prism


    【解决方案1】:

    UpdateSourceTrigger 属性的默认值是 LostFocus TextBox,这就是为什么在您将焦点从文本框移到其他控件之前不会更新 ViewModel 属性的原因(在您的情况下,点击按钮) .在绑定中将UpdateSourceTrigger 的值设置为PropertyChanged

    例如:

    <TextBox Name="ChannelSearch" 
             Text="{Binding Path=ChannelFilter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  
             TextChanged="ChannelSearch_TextChanged" />
    

    请参阅此 MSDN article 以了解有关 UpdateSourceTrigger 属性的更多信息。

    对于您最初的问题,您可以从 viewModel 上 ChannelFilter 属性的设置器中调用 doFilterChannels 方法(当然,不会阻塞 UI 线程)。

    【讨论】:

    • 完美。谢谢!在没有 WPF 知识的情况下,我被投入到这个项目中。上次我做一个桌面应用程序是在 MFC 中哈哈。仍在尝试了解这些差异。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2011-01-15
    • 2011-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-27
    • 1970-01-01
    • 2012-10-31
    相关资源
    最近更新 更多