2014-05-16 16 views
3

Caliburn.Micro允許爲視圖和視圖模型配置命名約定,但我找不到如何配置控件和方法之間的匹配。我知道我可以使用附加屬性Message.Attach,但如果可能的話,我想依賴約定。Caliburn.Micro框架中的控制命名約定

Caliburn.Micro的約定表示方法的名稱必須與控件相同。但這裏存在一個問題:他們經常以不同的名字命名。例如,SaveCancel是方法的好名字,但是按鈕的名稱很糟糕。 SaveButtonCancelButton是按鈕的好名字,但方法的名字不好。考慮到XAML的輸入類型不如C#,匈牙利語符號也可能很有用,但名稱如btnSavebtnCancel對於方法來說是不可接受的。

我能找到的最接近的東西是ConventionManager.GetPropertyCaseInsensitive,但它只適用於屬性,不適用於方法。

問題:如何配置Caliburn.Micro的約定,使其附加Save方法到SaveButton控制?

回答

3

這不是我以前試過的東西,但如果你看看Documentation,那就提到一個ViewModelBinder類,它負責修復屬性,方法等各個綁定到它們各自的ViewModels

你的情況特別關注:

ViewModelBinder.BindActions是FUNC鍵,如果需要,從而可以完全取代 。通過 添加或更改ElementConventions,ConventionManager還將影響如何將行動放在一起。 更多關於下面。

因此,基本上,通過定義自己的BindActions函數,應該有可能獲得您想要的行爲。

作爲一個開始的地方,您可以查看sourceViewModelBinder.BindActions並查看當前如何定義函數。

如果你切出的WinRT的特定代碼,你留下的東西,看起來像這樣(你可能不得不刪除日誌調用):

ViewModelBinder.BindActions = 
(namedElements, viewModelType) => 
{ 

    var methods = viewModelType.GetMethods(); 
    var unmatchedElements = namedElements.ToList(); 

    foreach (var method in methods) 
    { 
     var foundControl = unmatchedElements.FindName(method.Name); 

     if (foundControl == null) 
     { 
      Log.Info("Action Convention Not Applied: No actionable element for {0}.", method.Name); 
      continue; 
     } 

     unmatchedElements.Remove(foundControl); 

     var message = method.Name; 
     var parameters = method.GetParameters(); 

     if (parameters.Length > 0) 
     { 
      message += "("; 

      foreach (var parameter in parameters) 
      { 
       var paramName = parameter.Name; 
       var specialValue = "$" + paramName.ToLower(); 

       if (MessageBinder.SpecialValues.ContainsKey(specialValue)) 
        paramName = specialValue; 

       message += paramName + ","; 
      } 

      message = message.Remove(message.Length - 1, 1); 
      message += ")"; 
     } 

     Log.Info("Action Convention Applied: Action {0} on element {1}.", method.Name, message); 
     Message.SetAttach(foundControl, message); 
    } 

    return unmatchedElements; 
}; 

你可以看到Caliburn.Micro嘗試通過將ViewModel上的可用方法名稱與相應的View中存在的控件的名稱進行比較來將該方法綁定到控件上。

一種方法可能是簡單地添加第二次嘗試找到控件,搜索附加的Button的方法名稱。這似乎有點違反直覺(從名稱中刪除按鈕更合乎邏輯)。

if (foundControl == null) 
{ 
    // Check again for "<Method>Button" named FrameworkElements 
    foundControl = unmatchedElements.FindName(method.Name + "Button"); 

    if (foundControl == null) 
    { 
     Log.Info("Action Convention Not Applied: No actionable element for {0}.", method.Name); 
     continue; 
    } 
} 

顯然,如果你有一個名爲SaveButton和一個名爲Save,其中只有一個是最後一次遇到會被正確連接了控制,這將意味着什麼。解決方案取決於您是否還想保留原始綁定行爲,或僅僅是這種新行爲。

無論是哪種情況,都值得閱讀整個文檔鏈接,因爲它提到了諸如ViewModelBinder.ApplyConventionsByDefault標誌等其他感興趣的內容。