【问题标题】:Bind a method to xaml control将方法绑定到 xaml 控件
【发布时间】:2012-02-12 23:48:26
【问题描述】:

我需要将方法绑定到 xaml 文件中的自定义控件,而不是方法的结果。

基本上自定义控件会在某些条件匹配时触发该方法几次。

我该怎么做?

我在网上找到了一些解决方案,但大多数都是将方法的结果绑定到 xaml 中,这不是我要寻找的解决方案。

非常感谢。

【问题讨论】:

  • 感谢 ColinE 和 ChrisBD 的快速响应!但我认为命令并不适合我的情况,因为我们仍然需要根据自定义控件中的某些事件触发命令库。但是我找到了一个解决方案,我将在下面分享它。
  • 是的,我从这里得到了答案:stackoverflow.com/questions/5146946/…。这个问题已经是我的答案了。 :)

标签: wpf xaml binding


【解决方案1】:

您可以使用两种不同的方法:

  • Commands,公开一个 ICommand 类型的属性,您将其绑定到 UI 元素的 Command 属性。
  • 使用行为将 UI 事件关联到视图模型中的方法,例如使用 MVVM Light EventToCommandBehaviour

【讨论】:

    【解决方案2】:

    找到了这个很好的答案:

    Binding of static method/function to Func<T> property in XAML

    Simon Rasmussen 已经在他的问题示例代码中展示了我所需要的一切。

    【讨论】:

      【解决方案3】:

      您能否更具体地说明条件是什么? @ColineE 和 @ChrisBD 正确地指出 ICommands 和 EventTocommandBehavior 在许多情况下都会有所帮助,例如将按钮单击或鼠标悬停事件转换为 ViewModel 中的方法调用。 如果可以使用这些方法,我会提倡使用它们,因为它们被认为是最佳实践

      但是,有些情况需要比这更复杂的东西。一种解决方案是使用代码隐藏将 DataContext 转换为视图模型类型并直接调用该方法。例如:

      // Inside MyViewModel.cs 
      public class MyViewModel : INotifyPropertyChanged 
      { 
          // ... 
      } 
      
      // ...  
      // Inside MyControl.xaml.cs 
      public class MyControl : UserControl 
      { 
          public MyControl()  
          { 
              InitializeComponent();  
          } 
      
          pubilc void OnSomeConditionMatches() 
          { 
               var myViewModel = DataContext as MyViewModel; 
               if (myViewModel != null)  
               { 
                    // Hacky, but it works
                    myViewModel.CallCustomMethod();  
               }
          } 
      }
      

      这被认为有点 hacky,并且会在运行时使用 ViewModel 类型的知识污染代码隐藏。我们想要避免的事情,因为它打破了 View 和 ViewModel 之间的关注点分离。

      另一种方法是我自己在处理很少或没有数据绑定支持的自定义控件时使用的方法。通过使用视图上的接口和附加属性,您可以inject a view instance into the viewModel and manipulate it directly。一种混合 MVVM / MVP 模式,我创造了 MiVVM。

      UML

      Xaml:

      <!-- Assumes myViewModel is the viewmodel we are binding to --> 
      <!-- which has property InjectedUserControl of type IMyControl --> 
      <Example3:MyControl DataContext="{StaticResource myViewModel}" 
                          Injector.InjectThisInto="InjectedUserControl"> 
      </Example3:MyControl>
      

      代码:

      // Defines an interface to the usercontrol to  
      // manipulate directly from ViewModel 
      public interface IMyControl 
      { 
          // Our test method to call  
          void CallView(string message); 
      } 
      
      // Defines the usercontrol  
      public partial class MyControl : UserControl, IMyControl 
      { 
          public MyControl() 
          { 
              InitializeComponent(); 
          } 
      
          public void CallView(string message) 
          { 
              MessageBox.Show(message); 
          } 
      }
      
      public class MyViewModel 
      { 
          private IMyControl myControl; 
      
          public IMyControl InjectedUserControl 
          { 
              set
              { 
                  Debug.WriteLine(string.Format("Received Injected Control \"{0}\"", 
                      value == null ? "NULL" : value.GetType().Name)); 
      
                  this.myControl = value; 
                  this.OnInjectedObjectsChanged(); 
              } 
          } 
      
          private void OnInjectedObjectsChanged() 
          { 
              // Directly access the view via its interface 
              if (this.myControl != null) 
                  this.myControl.CallView("Hello From MyViewModel"); 
          } 
      }
      

      有关包含 Injector 附加属性源的可下载演示,请参阅this blog 帖子。还有this previous question,这是相关的。

      最好的问候,

      【讨论】:

      • 谢谢,你的hacky解决方案让我对我的问题有了新的想法,我也喜欢你之前想到的控制注入的想法。但是我得到了答案,请检查我在我的问题中的评论。非常感谢!
      • @tzuhsun 完全没有问题 - 很高兴你找到了答案! :) PS:麻省理工学院对 hack 的定义——“对原本不可能的问题的巧妙解决方案”
      【解决方案4】:

      您会希望绑定到 ICommand 的实现并让它调用您的类方法。

      Here's a good blog 描述了有关使用 ICommand 从 WPF 执行代码的更多信息。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-03-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-27
        • 2012-08-15
        • 1970-01-01
        • 2011-04-01
        相关资源
        最近更新 更多