我想使用Silverlight和WPF Toolkits的Accordion控件的Caliburn.Micro约定:
查看:
<Grid Background="White">
<Controls:Accordion x:Name="Items"/>
</Grid>
视图模型:
public class ShellViewModel : IShell
{
public ShellViewModel()
{
Items = new List<AccItemViewModel>
{
new AccItemViewModel
{
DisplayName = "header one",
Content = "content one"
},
new AccItemViewModel
{
DisplayName = "header two",
Content = "content two"
},
};
}
public IEnumerable<IScreen> Items { get; set; }
public class AccItemViewModel : Screen
{
public string Content { get; set; }
}
默认情况下,Caliburn将Accordion的ItemsSource中的元素绑定到AccordionItem标题中:
我添加了Accordion的ContentTemplate的约定:
private void AddCustomConventions()
{
ConventionManager.AddElementConvention<Accordion>
(Accordion.ItemsSourceProperty, "SelectedItem", "SelectionChanged")
.ApplyBinding =
(viewModelType, path, property, element, convention) =>
{
if (ConventionManager
.GetElementConvention(typeof(ItemsControl))
.ApplyBinding(viewModelType, path, property,
element, convention))
{
element.SetValue(Accordion.ContentTemplateProperty,
ConventionManager.DefaultItemTemplate);
return true;
}
return false;
};
}
实现了以下目标:
但我想将AccordionItem的标头绑定到AccItemViewModel(IScreen)的DisplayName,或者在AccItemViewModel上有一个Header视图模型属性。 AccordionItem有HeaderProperty和HeaderTemplateProperty,但我无法弄清楚如何将约定应用于这些。
答案 0 :(得分:2)
查看源代码下的WPF TabControl约定。这应该会让你走上正确的道路。
答案 1 :(得分:2)
看起来,手风琴确实与TabControl非常相似,我问题中片段的缺失部分是
ConventionManager
.ApplyHeaderTemplate(accordion,
ItemsControl.ItemTemplateProperty, viewModelType);
以下是为方便起见的完整约定(BTW此代码可以针对ItemsControl的多个后代进行推广):
ConventionManager.AddElementConvention<Accordion>(
ItemsControl.ItemsSourceProperty,
"ItemsSource", "SelectionChanged")
.ApplyBinding = (
viewModelType, path, property, element, convention) =>
{
if (!ConventionManager.SetBinding(
viewModelType, path, property, element, convention))
return false;
var accordion = (Accordion)element;
if (accordion.ContentTemplate == null
&& property.PropertyType.IsGenericType)
{
var itemType = property
.PropertyType
.GetGenericArguments()
.First();
if (!itemType.IsValueType &&
!typeof(string).IsAssignableFrom(itemType))
{
accordion.ContentTemplate =
ConventionManager.DefaultItemTemplate;
}
}
ConventionManager.ConfigureSelectedItem(
element, Selector.SelectedItemProperty,
viewModelType, path);
if (string.IsNullOrEmpty(accordion.DisplayMemberPath))
ConventionManager.ApplyHeaderTemplate(
accordion, ItemsControl.ItemTemplateProperty,
viewModelType);
return true;
};
ConventionManager.AddElementConvention<AccordionItem>(
ContentControl.ContentProperty,
"DataContext", "DataContextChanged");