2014-06-04 56 views
2

我想获得绑定到给定属性名称的TextBox的引用。 我想在不改变视图的情况下做到这一点。 有没有适当的方法来使用Caliburn Micro来做到这一点? 如果不是,什么是“足够好”的方式?使用Caliburn Micro从视图模型中的属性名称获取控件

public class MweViewModel : PropertyChangedBase 
{ 
    public MweViewModel() : base() 
    { 
     PropertyChanged += (object sender, PropertyChangedEventArgs e) => 
     { 
      // Find control (i.e. TextBox) bound to property with name e.PropertyName 
      TextBox textBox = ... 
     }; 
    } 
} 
+0

你最终的目标是什么?看起来你的'ViewModel'应该不会意识到你的'View'在这个范围内,你可能会采取另一种方法。这可能是您的问题确实是唯一的解决方案,但绝对值得探索您尝试实现的目标。 – Chris

+0

我是WPF初学者,所以这可能是错误的方法。这个想法是在继承视图模型中为属性标记的属性提供自动验证,而不必修改视图。设置自动验证相对简单。我遇到的问题是控制它的行为。我的想法是有权查看映射到属性更改的事件(通过'TextBox')。即如果有人在视图中执行此操作,请验证该字段。 – Linus

+0

我看到了,大概你仍然需要定义如何在你的视图中显示这些错误?这可能有一些有用的信息:http://blog.magnusmontin.net/2013/08/26/data-validation-in-wpf/然后,它可能不会= D – Chris

回答

1

我并不知道这是最明智的做法(这不是我一直试图做我自己),看着Documentation,有一个ViewModelBinder类是负责修复了的提各种特性,方法等与其各自的ViewModels的绑定。

上的BindProperties函数负责解析您的属性和它们最终绑定到的UI元素之间的绑定。您可以根据现有的代码定义您自己的函数,该代码可以跟踪所有绑定的建立情况,因此您可以在程序中的其他位置使用它们的记录。

使用existing code会给你这样的事情:

ViewModelBinder.BindProperties = (namedElements, viewModelType) => 
    { 
     var unmatchedElements = new List<FrameworkElement>(); 

     foreach (var element in namedElements) 
     { 
      var cleanName = element.Name.Trim('_'); 
      var parts = cleanName.Split(new[] { '_' }, StringSplitOptions.RemoveEmptyEntries); 

      var property = viewModelType.GetPropertyCaseInsensitive(parts[0]); 
      var interpretedViewModelType = viewModelType; 

      for (int i = 1; i < parts.Length && property != null; i++) 
      { 
       interpretedViewModelType = property.PropertyType; 
       property = interpretedViewModelType.GetPropertyCaseInsensitive(parts[i]); 
      } 

      if (property == null) 
      { 
       unmatchedElements.Add(element); 
       // Log.Info("Binding Convention Not Applied: Element {0} did not match a property.", element.Name); 
       continue; 
      } 

      var convention = ConventionManager.GetElementConvention(element.GetType()); 
      if (convention == null) 
      { 
       unmatchedElements.Add(element); 
       // Log.Warn("Binding Convention Not Applied: No conventions configured for {0}.", element.GetType()); 
       continue; 
      } 

      var applied = convention.ApplyBinding(
       interpretedViewModelType, 
       cleanName.Replace('_', '.'), 
       property, 
       element, 
       convention 
       ); 

      if (applied) 
      { 
       // Log.Info("Binding Convention Applied: Element {0}.", element.Name); 
      } 
      else 
      { 
       // Log.Info("Binding Convention Not Applied: Element {0} has existing binding.", element.Name); 
       unmatchedElements.Add(element); 
      } 
     } 

     return unmatchedElements; 
    }; 

在何时被添加绑定(当applied设置),你有所有你所需要的信息点。然后您可以存储特定的绑定(例如与TextBox相关的绑定)。

您可以使用这样的静态辞典(有可能是根据您的要求远的东西更合适):

 ViewModel Type Bound Property  List of Bound elements 
      |     |      | 
      |     |      | 
Dictionary<Type, Dictionary<PropertyInfo, List<FrameworkElement>>> 

你必须要小心空/完整性检查。

还有一些其他解决方案使用帮助程序方法来获取绑定的属性/控件,尽管它们通常必须遍历可视化树,这样,您就是在实际创建绑定的时候这样做的。

相关问题