Caliburn.Micro convention to set button's text and action
Some time ago I started to use a great project called Caliburn.Micro as a supporting MEF and MVVM framework for one of the bigger projects, I'm working on.It is a great project that help you to create very loosely coupled code in your project.
During the work on the project one of the first things that hit me and I wasn't able to find any clear solution to it was how to set Caliburn's convention to set button's content (Caption) and leave it's natural action convention (like action method call and Can property for availability selection).
I chose a convetion to have:
- every button's content save in ViewModel variable BtnName_Content
- action method BtnName()
- availability property in CanBtnName
private void setupElementConventions()
{
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) { continue; }
if(!(foundControl is ButtonBase))
unmatchedElements.Remove(foundControl); //Remove from named elements only non button elements
var triggers = Interaction.GetTriggers(foundControl);
if (triggers != null && triggers.Count > 0) { continue; }
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 += ")";
}
Message.SetAttach(foundControl, message);
}
return unmatchedElements;
};
ViewModelBinder.BindProperties += (namedElements, viewModelType) =>
{
var unmatchedElements = namedElements.ToList();
foreach (var frameworkElement in namedElements)
{
var contentPropertyName = frameworkElement.Name + "_Content"; // Nastavení vazby pro ButtonName_Content pro Content property elementu Button
var contentProperty = viewModelType.GetPropertyCaseInsensitive(contentPropertyName);
if (contentProperty != null)
{
unmatchedElements.Remove(frameworkElement); // Odstraň použití element ze seznamu named elementů
var convention = ConventionManager.GetElementConvention(typeof(ButtonBase));
ConventionManager.SetBindingWithoutBindingOverwrite(
viewModelType,
contentPropertyName,
contentProperty,
frameworkElement,
convention,
convention.GetBindableProperty(frameworkElement));
}
}
return unmatchedElements;
};
}
