Конвенция Caliburn.Micro для Accordion и AccordionItem

Я хотел бы использовать соглашения Caliburn.Micro для элемента управления Accordion из Silverlight и WPF Toolkits:

Вид:

<Grid Background="White">
    <Controls:Accordion x:Name="Items"/>
</Grid>

ViewModel:

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 привязывает элементы в ItemsSource Accordion к заголовкам AccordionItem:


Я добавил соглашение для шаблона содержимого Accordion:

    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 к DisplayName AccItemViewModel (IScreen), либо иметь свойство модели представления заголовка в AccItemViewModel. AccordionItem имеет HeaderProperty и HeaderTemplateProperty, но я не могу понять, как применить к ним соглашения.


person Sergey Aldoukhov    schedule 01.07.2011    source источник


Ответы (2)


Взгляните на соглашение WPF TabControl в источнике. Это должно направить вас на правильный путь.

person EisenbergEffect    schedule 01.07.2011

Как оказалось, Accordion действительно очень похож на TabControl, и недостающий фрагмент для фрагмента в моем вопросе был

ConventionManager
  .ApplyHeaderTemplate(accordion, 
     ItemsControl.ItemTemplateProperty, viewModelType);

Вот полное соглашение для вашего удобства (кстати, этот код можно обобщить для нескольких потомков 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");
person Sergey Aldoukhov    schedule 06.07.2011