WPF Prism Bound字段值在命令触发之前不可用

时间:2013-10-03 15:47:14

标签: c# wpf xaml mvvm prism

我在我的桌面WPF非Silverlight应用程序中实现了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文本每次都为null。让我感到困惑的是,如果我点击我在屏幕上创建的保存按钮,它会直接命中一个DelegateCommmand:

<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事件时?有没有更好的方法来处理这些情况?

1 个答案:

答案 0 :(得分:3)

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

e.g:

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

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

对于您的原始问题,您可以从viewModel上的doFilterChannels属性的setter调用ChannelFilter方法(当然,不会阻止UI线程)。