Привязка TreeView к SL4 к IGrouping с использованием Caliburn - PullRequest
3 голосов
/ 04 мая 2010

Я только начинаю в мире SL и пытаюсь использовать Caliburn NavigationShell в качестве отправной точки. Я преобразовал решение в SL4 и использую Caliburn из багажника.

Чтобы создать базовую навигацию, я немного не уверен (ну, вполне), как я могу отобразить исходную панель кнопок StackPanel в виде разборного дерева.

Я изменил ITaskBarItem на простое свойство GroupName

public interface ITaskBarItem : IEntryPoint
{
    BitmapImage Icon { get; }
    string DisplayName { get; }
    string GroupName { get;}
}

затем я выставляю это в ShellViewModel для просмотра:

    public IEnumerable<IGrouping<string, ITaskBarItem>> TaskBarItems
    {
        get { return _taskBarItems.GroupBy(t => t.GroupName); }
    }

Как я могу сделать разметку xaml, чтобы получить простую иерархию?

Как связать действия без использования кнопок?

> GroupName
    DisplayName
    DisplayName
    DisplayName

> GroupName
    DisplayName
    DisplayName
    DisplayName
    ...

Имейте в виду, это MVVM, поэтому я не собираюсь использовать код или события для этого ...

Ответы [ 2 ]

2 голосов
/ 08 сентября 2010

Здесь есть пара трудностей. Во-первых, вот моя разметка:

<ItemsControl x:Name="TaskBarItems">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding Converter={StaticResource groupName}}"
                            FontWeight="Bold" />
                <ItemsControl ItemsSource="{Binding}"
                                Margin="12 0 0 0">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <StackPanel>
                                <TextBlock Text="{Binding DisplayName}" />
                            </StackPanel>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

и моя раковина:

public class ShellViewModel : IShell
{
    readonly TaskBarItemViewModel[] taskBarItems;

    public ShellViewModel()
    {
        taskBarItems = new[]
            {
                new TaskBarItemViewModel {GroupName = "Animal", DisplayName = "Monkey"},
                new TaskBarItemViewModel {GroupName = "Animal", DisplayName = "Cat"},
                new TaskBarItemViewModel {GroupName = "Animal", DisplayName = "Dog"},
                new TaskBarItemViewModel {GroupName = "Mineral", DisplayName = "Biotite"},
                new TaskBarItemViewModel {GroupName = "Mineral", DisplayName = "Phlogopite"},
                new TaskBarItemViewModel {GroupName = "Mineral", DisplayName = "Lepidolite"},
            };
    }

    public IEnumerable<IGrouping<string, TaskBarItemViewModel>> TaskBarItems
    {
        get
        {
            return taskBarItems.GroupBy(t => t.GroupName).ToList();
        }
    }
}

Calibrun Micro (cm) будет связывать элементы управления TaskBarItems по соглашению. Тем не менее, остальные не будут работать по соглашению по нескольким причинам. Он находится в DataTemplate, поэтому мы обычно используем Bind.Model. Однако это не сработает, потому что тип каждого элемента в itemscontrol является общим (IGrouping). Соглашения по умолчанию не могут обработать поиск представления для этого. Поэтому мы предоставляем встроенный шаблон данных.

Во-вторых, свойство Key представляется реализованным как явный интерфейс. Это означает, что Silverlight не может связываться с ним. Я сделал простой конвертер, который привязывается к группе и извлекает ключ:

public class GroupNameConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return ((IGrouping<string,TaskBarItemViewModel>)value).Key;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Далее, поскольку группировка сама по себе является IEnumerable, мы должны напрямую связать ItemsSource вложенного элемента управления. Мы не можем использовать соглашения, потому что в IGrouping нет свойства, которое возвращает элементы. (Хотя, если бы было, у нас, вероятно, все еще была бы явная проблема с интерфейсом.)

Относительно вашего второго вопроса. Вы можете привязать действие к любому событию. Смотрите документацию здесь: http://caliburnmicro.codeplex.com/wikipage?title=All%20About%20Actions&referringTitle=Documentation

1 голос
/ 18 января 2011

Преобразователь значений из ответа Кристофера можно обобщить так:


public class ExplicitPropertyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value == null ? null : GetPropertyValue(value, (string)parameter);
    }

    private static object GetPropertyValue(object target, string name)
    {
        return (
                from type in target.GetType().GetInterfaces()
                from prop in type.GetProperties()
                where prop.Name == name && prop.CanRead
                select prop.GetValue(target, new object[0])
            ).FirstOrDefault();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

И использование здесь:


<TextBlock
    Text="{
        Binding
        Converter={StaticResource ExplicitPropertyConverter},
        ConverterParameter=Key
    }"
    />

Этот конвертер поддерживает любые свойства любого интерфейса. Больше информации в моем блоге .

...