Accibion​​和AccordionItem的Caliburn.Micro惯例

时间:2011-07-01 00:08:26

标签: silverlight caliburn.micro

我想使用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,但我无法弄清楚如何将约定应用于这些。

2 个答案:

答案 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");