简体   繁体   中英

How to Style Combination of Multiple Collections Within ContextMenu in WPF?

public class MainViewModel
{
    public MainViewModel()
    {
        var iconGeometry = Geometry.Parse("M150 0 L75 200 L225 200 Z");
        OpenFiles =
            new ObservableCollection<File>()
            {
                new File { IconGeometry = iconGeometry, Filename = "Document.docx" },
                new File { IconGeometry = iconGeometry, Filename = "Evidence.xlsx" }
            };

        ActiveRecords =
            new ObservableCollection<Record>()
            {
                new Record { RecordIconGeometry = iconGeometry, Name = "The First Record" }
            };
    }

    public ObservableCollection<File> OpenFiles { get; set; }

    public ObservableCollection<Record> ActiveRecords { get; set; }
}

Based on the MainViewModel , I would like to create a ContextMenu that combines one custom item and items from both the OpenFiles and the ActiveRecords collection.

<ContextMenu>
    <ContextMenu.Resources>
        <CollectionViewSource x:Key="ActiveRecordsCollectionSource"
                                Source="{Binding ActiveRecords}" />
        <CollectionViewSource x:Key="OpenFileCollectionSource"
                                Source="{Binding OpenFiles}" />
        <DataTemplate DataType="{x:Type local:File}">
            <TextBlock><Run Text="Close " /><Run Text="{Binding FileName}" /></TextBlock>
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:Record}">
            <TextBlock><Run Text="Close " /><Run Text="{Binding Label}" /></TextBlock>
        </DataTemplate>
    </ContextMenu.Resources>
    <ContextMenu.ItemsSource>
        <CompositeCollection>
            <CollectionContainer Collection="{Binding Source={StaticResource ActiveRecordsCollectionSource}}" />
            <Separator />
            <CollectionContainer Collection="{Binding Source={StaticResource OpenFileCollectionSource}}" />
            <Separator />
            <MenuItem Header="Close All">
                <MenuItem.Icon>
                    <Path Width="16"
                            Height="16"
                            Fill="Black"
                            Stretch="Uniform"
                            Data="M10.185,1.417c-4.741,0-8.583,3.842-8.583,8.583c0,4.74,3.842,8.582,8.583,8.582S18.768,14.74,18.768,10C18.768,5.259,14.926,1.417,10.185,1.417 M10.185,17.68c-4.235,0-7.679-3.445-7.679-7.68c0-4.235,3.444-7.679,7.679-7.679S17.864,5.765,17.864,10C17.864,14.234,14.42,17.68,10.185,17.68 M10.824,10l2.842-2.844c0.178-0.176,0.178-0.46,0-0.637c-0.177-0.178-0.461-0.178-0.637,0l-2.844,2.841L7.341,6.52c-0.176-0.178-0.46-0.178-0.637,0c-0.178,0.176-0.178,0.461,0,0.637L9.546,10l-2.841,2.844c-0.178,0.176-0.178,0.461,0,0.637c0.178,0.178,0.459,0.178,0.637,0l2.844-2.841l2.844,2.841c0.178,0.178,0.459,0.178,0.637,0c0.178-0.176,0.178-0.461,0-0.637L10.824,10z" />
                </MenuItem.Icon>
            </MenuItem>
        </CompositeCollection>
    </ContextMenu.ItemsSource>
</ContextMenu>

How can I style the items to show both the icon and the name ? If I need ItemContainerStyle to set the icon , how to change the binding path ( IconGeometry vs. RecordIconGeometry ) based on the Object Type ?

If I need ItemContainerStyle to set the icon, how to change the binding path ( IconGeometry vs. RecordIconGeometry ) based on the Object Type?

You could use a converter that returns the appropriate object:

<ContextMenu>
    <ContextMenu.Resources>
        ...
        <local:Converter x:Key="conv" />
    </ContextMenu.Resources>
    <ContextMenu.ItemContainerStyle>
        <Style TargetType="MenuItem">
            <Setter Property="Icon" Value="{Binding Path=., Converter={StaticResource conv}}" />
        </Style>
    </ContextMenu.ItemContainerStyle>
</ContextMenu>

public class Converter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        File file = value as File;
        if (file != null)
            return file.IconGeometry;

        Record record = value as Record;
        if (record != null)
            return record.RecordIconGeometry;

        return value;
    }

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

I am afraid there is no way to call the GetType() method or use the as operator in XAML though.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM