wpf - 在 ShowDialog (WPF MVVM) 中将 UpdateSourceTrigger 设置为显式

标签 wpf data-binding mvvm showdialog updatesourcetrigger

我看到了这个例子 - Binding.UpdateSourceTrigger Property

在示例中,UpdateSourceTrigger 设置为 Explicit,然后在 View 代码中他调用 TextBox 名称的 UpdateSource。

但是,如果我使用 MVVM dp,我不希望我的控件和源属性的名称在 VM 中而不是在 View 中,那么将控件绑定(bind)到 VM 属性并将 UpdateSourceTrigger 设置为显式的正确方法是什么?

我想这样做是因为在我的情况下是它的 ShowDialog 窗口,我希望源只有在用户单击“确定”时才会更新

提前致谢!

最佳答案

如果您真正使用 MVVM,那么您的 OK 按钮单击必须由某些 Command 处理。 .此命令必须来自您的 ViewModel . Expliticly绑定(bind)属性必须来自您的 ViewModel再次。那么是什么阻止了你。

  • 请勿使用 Explicit绑定(bind)但使用 OneWay捆绑。
  • 在你的按钮中,绑定(bind)一个命令并将命令参数绑定(bind)到 OneWay绑定(bind)依赖属性。
  • 在您的 Command 的 Execute 处理程序(必须是您的 ViewModel 中的某个方法)中,使用传入的参数更改 ViewModel 的属性。
  • 提高NotifyPropertyChanged从您的 ViewModel 获取该房产.

  • 例如。

    假设我需要在单击 OK 按钮时将 TextBox 的 Text 更新回我的模型。

    所以为此我有一个 EmployeeViewModel具有 EmployeeName 的类其中的属性(property)。该属性有一个 getter 和一个 setter。 setter 引发属性更改通知。 View 模型还有另一个类型为 ICommand 的属性。命名 SaveNameCommand返回一个命令让我执行。
    EmployeeViewModel是我的 View 的数据上下文类型。 Myview 有一个 TextBox (命名为 x:Name="EmployeeNameTxBx")OneWay绑定(bind)到 EmployeeName和一个按钮为 OK .我绑定(bind) Button.Command属性(property)到EmployeeViewModel.SaveNameCommand属性(property)和Button.CommandParameter绑定(bind)到EmployeeNameTxBx.Text属性(property)。
          <StackPanel>
              <TextBox x:Name="EmployeeNameTxBx"
                       Text="{Binding EmployeeName, Mode=OneWay}" />
              <Button Content="OK"
                      Command="{Binding SaveNameCommand}"
                      CommandParameter="{Bidning Text, ElementName=EmployeeNameTxBx}" />
          </StackPanel>
    

    在我的 EmployeeViewModel 里面我有 OnSaveNameCommandExecute(object param)执行我的方法 SaveNameCommand .

    在此执行此代码...
         var text = (string)param;
         this.EmployeeName = text;
    

    这样只有单击 OK 按钮,将 TextBox 的文本更新回 EmployeeName模型的属性。

    编辑

    查看您下面的评论,我发现您正在尝试在 UI 上实现验证。现在这稍微改变了一些事情。
    IDataErrorInfo和相关验证仅在您的输入控件(例如文本框)为 时才有效。双向边界。是的,这就是它的意图。所以现在你可能会问“如果我们使用 IDataErrorInfo,这是否意味着不允许无效数据传递给模型的整个概念在 MVVM 中是徒劳的”?

    实际上不!

    请参阅 MVVM 不强制执行仅应返回有效数据的规则。它接受无效数据,这就是 IDataErrorInfo工作并引发错误通知。关键是 ViewModel 只是 软拷贝 您的 View ,所以它可以是 .应该确保的是,这种肮脏不是 promise 到您的外部接口(interface),例如服务或数据库。

    这种无效的数据流应该受到ViewModel的限制。通过测试无效数据。如果我们有 TwoWay,数据就会出现。绑定(bind)启用。因此,考虑到您正在实现 IDataErrorInfo那么你需要有 TwoWay MVVM 中完全允许的绑定(bind)。

    方法一:

    如果我想在单击按钮时显式验证 UI 上的某些项目怎么办?

    为此,请使用延迟验证技巧。在您的 ViewModel 中有一个名为 isValidating 的标志。默认设置为false。

    在您的 IDataErrorInfo.this属性通过检查 isValidating 标志跳过验证...
        string IDataErrorInfo.this[string columnName]
        {
          get
          {
            if (!isValidating) return string.Empty;
    
            string result = string.Empty;
            bool value = false;
    
            if (columnName == "EmployeeName")
            {
                if (string.IsNullOrEmpty(AccountType))
                {
                    result = "EmployeeName cannot be empty!";
                    value = true;
                }
            }
            return result;
          }
        }
    

    然后在您的 OK 命令执行处理程序中,检查员工姓名,然后为同一属性引发属性更改通知事件...
        private void OnSaveNameCommandExecute(object param)
        {
             isValidating = true;
             this.NotifyPropertyChanged("EmployeeName");
             isValidating = false;
        }
    

    这仅在您单击确定时触发验证。请记住 EmployeeName必须包含无效数据才能进行验证。

    方法二:

    如果我想在 MVVM 中显式更新没有 TwoWay 模式的绑定(bind)怎么办?

    那么你将不得不使用 Attached Behavior .该行为将附加到“确定”按钮,并将接受需要刷新其绑定(bind)的所有项目的列表。
           <Button Content="OK">
               <local:SpecialBindingBehavior.DependentControls>
                    <MultiBinding Converter="{StaticResource ListMaker}">
                        <Binding ElementName="EmployeeNameTxBx" />
                        <Binding ElementName="EmployeeSalaryTxBx" />
                        ....
                    <MultiBinding>
               </local:SpecialBindingBehavior.DependentControls>
           </Button>
    
    ListMakerIMultiValueConverter这只是将值转换为列表...
           Convert(object[] values, ...)
           {
                return values.ToList();
           }
    

    在您的 SpecialBindingBehavior有一个 DependentControls属性更改处理程序...
          private static void OnDependentControlsChanged(
              DependencyObject depObj,
              DependencyPropertyChangedEventArgs e) 
          {
               var button = sender as Button;
               if (button != null && e.NewValue is IList)
               {
                   button.Click 
                        += new RoutedEventHandler(
                             (object s, RoutedEventArgs args) =>
                             {
                                  foreach(var element in (IList)e.NewValue)
                                  {
                                     var bndExp
                                       = ((TextBox)element).GetBindingExpression(
                                           ((TextBox)element).Textproperty);
    
                                     bndExp.UpdateSource();
                                  }
                             });
               }
          }
    

    但我还是建议你用我以前的基于纯 MVVM 的 **方法 1 .

    关于wpf - 在 ShowDialog (WPF MVVM) 中将 UpdateSourceTrigger 设置为显式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7657996/

    相关文章:

    WPF数据网格问题

    c# - 使用 MVVM 显示枚举 equalivent 字符串值

    具有非依赖属性的 wpf mvvm?

    c# - WPF、C#、MVVM 在模型中静态变量的变化中动态通知 ViewModel

    wpf - WPF中的PropertyMetaData、UIPropertyMetadata、FrameworkMetaData有什么区别

    wpf - 如何在 XAML 中构建控件网格?

    wpf - 使用 XAML 为 UserControl 中的所有元素添加前景色 setter

    首先将 WPF 数据绑定(bind)到数据网格和 Entity Framework 数据库

    wpf - DataTemplate.Triggers 与 Style.Triggers

    wpf - 您知道使用MVVM的任何实际有用的WPF/Silverlight应用程序吗?