我非常喜欢Caliburn和命名约定绑定,并对此感到惊讶 可见性的约束方式与“CanNAME”公约用于保护动作的方式不同。 据我所知,只有在Caliburn中明确使用Binding时才使用BooleanToVisibilityConverter,而不是像guard方法那样自动使用。所以我想修改源代码以自动绑定到“bool?ControlNameIsVisible()”(null等于崩溃)或类似。我想知道这是否是正确的方法,如果有人已经完成了实施并且可以在这里分享它。如果这样做。
答案 0 :(得分:18)
如果你愿意,你可以使用这种方法,这是完全合理的。另一种方法是在视图模型上使用与布尔属性同名的Border。 Caliburn.Micro将根据布尔属性的值设置Border的可见性。
<Border x:Name="ControlIsVisible">
<TextBox x:Name="MyControl" ... />
</Border>
答案 1 :(得分:9)
如果你想要一个通用的解决方案,这就是我最终的结果,基于:Adding a convention for IsEnabled to Caliburn.Micro
请注意覆盖BindActions以及BindProperties,以便您可以检查对其绑定操作的内容的可见性。
protected override void Configure()
{
base.Configure();
ConventionManager.AddElementConvention<UIElement>(UIElement.VisibilityProperty, "Visibility", "VisibilityChanged");
var baseBindProperties = ViewModelBinder.BindProperties;
ViewModelBinder.BindProperties =
(frameWorkElements, viewModel) =>
{
BindVisiblityProperties(frameWorkElements, viewModel);
return baseBindProperties(frameWorkElements, viewModel);
};
// Need to override BindActions as well, as it's called first and filters out anything it binds to before
// BindProperties is called.
var baseBindActions = ViewModelBinder.BindActions;
ViewModelBinder.BindActions =
(frameWorkElements, viewModel) =>
{
BindVisiblityProperties(frameWorkElements, viewModel);
return baseBindActions(frameWorkElements, viewModel);
};
}
void BindVisiblityProperties(IEnumerable<FrameworkElement> frameWorkElements, Type viewModel)
{
foreach (var frameworkElement in frameWorkElements)
{
var propertyName = frameworkElement.Name + "IsVisible";
var property = viewModel.GetPropertyCaseInsensitive(propertyName);
if (property != null)
{
var convention = ConventionManager
.GetElementConvention(typeof(FrameworkElement));
ConventionManager.SetBindingWithoutBindingOverwrite(
viewModel,
propertyName,
property,
frameworkElement,
convention,
convention.GetBindableProperty(frameworkElement));
}
}
}