将设计时间菜单元素组合成数据绑定菜单项绑定

时间:2016-02-25 10:58:53

标签: wpf

希望我在问题上得到了白话,所以我不会完全抛弃人。

我有一个数据绑定菜单,并使用HierarchicalDataTemplate来处理绑定对象中的各种嵌套类型。到目前为止,一切都在极好地发挥作用;但是现在我想为某种类型的菜单项添加一些额外的菜单项,但当然会破坏绑定,因为我无法绑定到已经包含元素的集合。 CompositeCollection似乎正是我要找的,但在尝试将其应用到我的HierarchicalDataTemplate时,我一直遇到语法错误。

        <Menu.Resources>
            <HierarchicalDataTemplate DataType="{x:Type ODIF:PluginContainer}" ItemsSource="{Binding Instance.Devices}">
                <HierarchicalDataTemplate.ItemsSource>
                    <CompositeCollection>
                        <CollectionContainer Collection="{Binding Instance.Devices}"/>
                        <MenuItem>One more item!</MenuItem>
                        <MenuItem>Two more items!</MenuItem>
                    </CompositeCollection>
                </HierarchicalDataTemplate.ItemsSource>
                <StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
                    <Image Source="{Binding PluginIcon}" Width="16" Height="16">
                        <Image.Style>
                            <Style TargetType="{x:Type Image}">
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding PluginIcon}" Value="{x:Null}">
                                        <Setter Property="Visibility" Value="Collapsed" />
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </Image.Style>
                    </Image>
                    <TextBlock Text="{Binding PluginName}"/>
                </StackPanel>
            </HierarchicalDataTemplate>
            <HierarchicalDataTemplate DataType="{x:Type ODIF:Device}" ItemsSource="{Binding InputChannels}">
                <StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
                    <Image Source="{Binding StatusIcon}" Width="16" Height="16">
                        <Image.Style>
                            <Style TargetType="{x:Type Image}">
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding StatusIcon}" Value="{x:Null}">
                                        <Setter Property="Visibility" Value="Collapsed" />
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </Image.Style>
                    </Image>
                    <TextBlock Text="{Binding DeviceName}"/>
                </StackPanel>
            </HierarchicalDataTemplate>
            <HierarchicalDataTemplate DataType="{x:Type ODIF:DeviceChannel}">
                <local:ChannelBox Channel="{Binding}" Width="200" Click="ChannelClicked"/>
            </HierarchicalDataTemplate>
        </Menu.Resources>

这引发:

  

无法分配指定的值。以下类型是   预期:&#34; BindingBase&#34;。

  

Property&#39; ItemsSource&#39;不支持类型&#39; CompositeCollection&#39;的值。

1 个答案:

答案 0 :(得分:1)

我猜您必须使用converter来解决您的问题。

假设MenuModel是表示菜单项的类。这很简单:

public class MenuModel
{
    private List<MenuModel> children = new List<MenuModel>();

    public string Description { get; set; }
    public IList Children
    {
        get
        {
            return children;
        }
    }
}

现在我们有了XAML:

<Window.Resources>

    <collections:ArrayList x:Key="someOtherMenus">
        <local:MenuModel Description="Menu A">
            <local:MenuModel.Children>
                <local:MenuModel Description="SubMenu i" />
                <local:MenuModel Description="SubMenu ii" />
            </local:MenuModel.Children>
        </local:MenuModel>
        <local:MenuModel Description="Menu B" />
    </collections:ArrayList>

</Window.Resources>

<DockPanel>
    <Menu DockPanel.Dock="Top" Margin="3" ItemsSource="{Binding MenuModels}">
        <Menu.ItemTemplate>
            <HierarchicalDataTemplate>
                <HierarchicalDataTemplate.ItemsSource>
                    <Binding ConverterParameter="someOtherMenus">
                        <Binding.Converter>
                            <local:CompositeCollectionConverter />
                        </Binding.Converter>
                    </Binding>
                </HierarchicalDataTemplate.ItemsSource>


                <TextBlock Text="{Binding Description}" Margin="3" />
            </HierarchicalDataTemplate>
        </Menu.ItemTemplate>
    </Menu>
    <TextBlock Text="text" Margin="10" />
</DockPanel>

现在我们可以考虑转换器实现:

public class CompositeCollectionConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        MenuModel menuModel = value as MenuModel;

        if (parameter != null)
        {
            CollectionContainer collectionContainer = new CollectionContainer();
            collectionContainer.Collection = menuModel.Children;

            CompositeCollection compositeCollection = new CompositeCollection();
            compositeCollection.Add(collectionContainer);

            collectionContainer = new CollectionContainer();
            collectionContainer.Collection = (IEnumerable)App.Current.MainWindow.FindResource(parameter);
            compositeCollection.Add(collectionContainer);

            return compositeCollection;
        }
        else
        {
            return menuModel.Children;
        }
    }

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

正如您所看到的,它使用其参数来获取特定资源(在我们的示例中,我使用名为&#34的资源; someOtherMenus&#34;,这是MenuModels的IEnumerable。

当然HierarchicalDataTemplate是递归的,所以&#34; someOtherMenus&#34; MenuModels的每个级别(但第一个)都会添加Menu

我希望我的样本可以帮助你。