3

我刚刚开始使用 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 标记以便获得简单的层次结构?

如何在不使用按钮的情况下绑定动作?

> 组名
    显示名称
    显示名称
    显示名称

> 组名
    显示名称
    显示名称
    显示名称
    ...

请注意,这是 MVVM,所以我不会使用背后的代码或事件来做到这一点......

4

2 回答 2

2

这里有几个困难。首先,这是我的标记:

<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) 将按照约定绑定 itemscontrol、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

于 2010-09-08T15:06:44.907 回答
1

Christopher's answer中的值转换器可以概括如下:


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
    }"
    />

该转换器支持任何接口的任何属性。更多信息在我的博客中。

于 2011-01-18T10:59:14.507 回答