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

标签 c# wpf xaml mvvm prism

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

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();
    }

View 模型:
 //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 文本每次都是空的。开始让我难以置信的是,如果我点击了我在屏幕上制作的保存按钮,它直接点击了 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 事件时发生?有没有更好的方法来处理这些情况?

最佳答案

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

例如:

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

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

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

关于c# - WPF Prism Bound 字段值在命令触发之前不可用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19163550/

相关文章:

c# - 转换到一个奇怪的重复派生类

c# - 如何处理 MVC 中的 2 对 1 关系?

c# - 如何将WPF效果颜色绑定(bind)到ControlTemplate的前景或背景

WPF MVVM - 单个 PropertyChanged 可以更新 DataTemplate 的所有数据绑定(bind)吗?

c# - 如何延迟对列表中属性的调用?

c# - 限制从网站外部访问操作

c# - 包含、存在和任何的性能基准测试

c# - 什么是 MVVM 处理 “insertion” 的正确方法

c# - 如何在 silverlight 中的 xaml 和 c# 之间共享数字常量

xaml - 在 ContentView 中声明转换器会导致空白的 xamarin 表单页面