开发者

Caliburn.Micro convention for Accordion and AccordionItem

开发者 https://www.devze.com 2023-03-16 09:48 出处:网络
I\'d like to use Caliburn.Micro conventions for the Accordion control from Silverlight and WPF Toolkits:

I'd like to use Caliburn.Micro conventions for the Accordion control from Silverlight and WPF Toolkits:

View:

<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
                            {
                          开发者_JAVA技巧      DisplayName = "header two", 
                                Content = "content two"
                            },
                    };
    }

    public IEnumerable<IScreen> Items { get; set; }


    public class AccItemViewModel : Screen
    {
        public string Content { get; set; }
    }

By default, Caliburn binds elements in Accordion's ItemsSource into AccordionItem headers:

Caliburn.Micro convention for Accordion and AccordionItem

I have added the convention for the Accordion's 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;
        };
    }

which achieved the following:

Caliburn.Micro convention for Accordion and AccordionItem

but I'd like to either bind the AccordionItem's header to DisplayName of the AccItemViewModel(IScreen) or have a Header view model property on AccItemViewModel. AccordionItem has HeaderProperty and HeaderTemplateProperty, but I can't figure out how to apply conventions to these.


Have a look at the WPF TabControl convention under source. That should put you on the right path.


As it appears, the Accordion is indeed extremely similar to TabControl, and the missing piece for the snippet in my question was

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

Here is the complete convention for your convenience (BTW this code can be generalized for multiple descendants of the 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");
0

精彩评论

暂无评论...
验证码 换一张
取 消