2014-06-04 59 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>>> 

你必須要小心空/完整性檢查。

還有一些其他解決方案使用幫助程序方法來獲取綁定的屬性/控件,儘管它們通常必須遍歷可視化樹,這樣,您就是在實際創建綁定的時候這樣做的。

相關問題