Setting MenuItem icon from binary image, in WPF (by C#)

رضا جافری 1,291 Reputation points
2022-02-11T11:48:47.62+00:00

First and foremost, I apologize for my grammatical errors; my first language is Persian (Iran).
I have custom Context Menu and MenuItem.
I want to set the MenuItem icon source from the binary image.
These are my codes:
XAML:

    <LinearGradientBrush x:Key="ContextMenuBackground" EndPoint="0,1" StartPoint="0,0">  
        <GradientStop Color="#e9f1cc" Offset="1"/>  
        <GradientStop Color="#cbd3ae" Offset="0.5"/>  
        <GradientStop Color="#858d68" Offset="0"/>  
    </LinearGradientBrush>  
    <Geometry x:Key="Checkmark">M 0,5.1 L 1.7,5.2 L 3.4,7.1 L 8,0.4 L 9.2,0 L 3.3,10.8 Z</Geometry>  
    <Style x:Key="{x:Type MenuItem}" TargetType="{x:Type MenuItem}">  
        <Setter Property="Template">  
            <Setter.Value>  
                <ControlTemplate TargetType="{x:Type MenuItem}">  
                    <Grid SnapsToDevicePixels="true">  
                        <Rectangle x:Name="BG" Fill="{TemplateBinding Background}" RadiusY="9" RadiusX="9" Stroke="{TemplateBinding BorderBrush}" StrokeThickness="1"/>  
                        <Rectangle x:Name="InnerBorder" Margin="1" RadiusY="9" RadiusX="9"/>  
                        <Grid>  
                            <Grid.ColumnDefinitions>  
                                <ColumnDefinition MinWidth="24" SharedSizeGroup="MenuItemIconColumnGroup" Width="Auto"/>  
                                <ColumnDefinition Width="4"/>  
                                <ColumnDefinition Width="*"/>  
                                <ColumnDefinition Width="37"/>  
                                <ColumnDefinition SharedSizeGroup="MenuItemIGTColumnGroup" Width="Auto"/>  
                                <ColumnDefinition Width="17"/>  
                            </Grid.ColumnDefinitions>  
                            <ContentPresenter x:Name="Icon" ContentSource="Icon" Margin="1" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center"/>  
                            <Border x:Name="GlyphPanel" BorderBrush="#CDD3E6" BorderThickness="1" Background="#E6EFF4" CornerRadius="3" Height="22" Margin="1" Visibility="Hidden" Width="22">  
                                <Path x:Name="Glyph" Data="{StaticResource Checkmark}" Fill="#0C12A1" FlowDirection="LeftToRight" Height="11" Width="9"/>  
                            </Border>  
                            <ContentPresenter Grid.Column="2" ContentSource="Header" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>  
                            <TextBlock Grid.Column="4" Margin="{TemplateBinding Padding}" Text="{TemplateBinding InputGestureText}"/>  
                        </Grid>  
                    </Grid>  
                    <ControlTemplate.Triggers>  
                        <Trigger Property="Icon" Value="True">  
                            <Setter Property="Visibility" TargetName="Icon" Value="Collapsed"/>  
                        </Trigger>  
                        <Trigger Property="IsChecked" Value="True">  
                            <Setter Property="Visibility" TargetName="GlyphPanel" Value="Visible"/>  
                            <Setter Property="Visibility" TargetName="Icon" Value="Collapsed"/>  
                        </Trigger>  
                        <Trigger Property="IsHighlighted" Value="True">  
                            <Setter Property="Fill" TargetName="BG">  
                                <Setter.Value>  
                                    <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">  
                                        <GradientStop Color="#7200F000" Offset="0"/>  
                                        <GradientStop Color="#72B4FFB4" Offset="0.25"/>  
                                        <GradientStop Color="White" Offset="0.5"/>  
                                        <GradientStop Color="#72FFB4B4" Offset="0.75"/>  
                                        <GradientStop Color="#72F00000" Offset="1"/>  
                                    </LinearGradientBrush>  
                                </Setter.Value>  
                            </Setter>  
                            <Setter Property="Stroke" TargetName="BG" Value="#8071CBF1"/>  
                            <Setter Property="Stroke" TargetName="InnerBorder" Value="#40FFFFFF"/>  
                        </Trigger>  
                        <Trigger Property="IsEnabled" Value="false">  
                            <Setter Property="Foreground" Value="#FF535252"/>  
                            <Setter Property="Background" TargetName="GlyphPanel" Value="#EEE9E9"/>  
                            <Setter Property="BorderBrush" TargetName="GlyphPanel" Value="#DBD6D6"/>  
                            <Setter Property="Fill" TargetName="Glyph" Value="#848589"/>  
                        </Trigger>  
                    </ControlTemplate.Triggers>  
                </ControlTemplate>  
            </Setter.Value>  
        </Setter>  
    </Style>  
    <Style x:Key="ContextMenuStyle" TargetType="ContextMenu">  
        <Setter Property="SnapsToDevicePixels" Value="True" />  
        <Setter Property="OverridesDefaultStyle" Value="True" />  
        <Setter Property="Grid.IsSharedSizeScope" Value="True" />  
        <Setter Property="HasDropShadow" Value="True" />  
        <Setter Property="Template">  
            <Setter.Value>  
                <ControlTemplate TargetType="ContextMenu">  
                    <Border Background="{StaticResource ContextMenuBackground}" BorderBrush="DarkGray" BorderThickness="0.7" CornerRadius="9">  
                        <ItemsPresenter/>  
                    </Border>  
                </ControlTemplate>  
            </Setter.Value>  
        </Setter>  
    </Style>  
    <ContextMenu x:Key="CustomContextMenu" Style="{StaticResource ContextMenuStyle}">  
        <MenuItem x:Name="CopyMenu" Header="Copy" Command="Copy" Height="32" Icon="{Binding}" Cursor="Hand"/>  
        <MenuItem x:Name="CutMenu" Header="Cut" Command="Cut" Height="32" Icon="{Binding}" Cursor="Hand"/>  
        <MenuItem x:Name="PasteMenu" Header="Paste" Command="Paste" Height="32" Icon="{Binding}" Cursor="Hand"/>  
    </ContextMenu>  
    <TextBox x:Name="AdminName_TextBox" GotFocus="AdminName_TextBox_GotFocus" LostFocus="AdminName_TextBox_LostFocus" ContextMenu="{StaticResource CustomContextMenu}" Padding="4,4,0,0" Template="{StaticResource TextBoxControlTemplate}" HorizontalAlignment="Left" Height="30" TextWrapping="Wrap" VerticalAlignment="Top" Width="267" Margin="21,63.5,0,0"/>  

C#:

    public AuthenticationWindow()  
    {  
        InitializeComponent();  
        ContextMenu CustomContextMenu = this.Resources["CustomContextMenu"] as ContextMenu;  
        MenuItem CopyMenuItem = CustomContextMenu.Items[0] as MenuItem;  
        MenuItem CutMenuItem = CustomContextMenu.Items[1] as MenuItem;  
        MenuItem PasteMenuItem = CustomContextMenu.Items[2] as MenuItem;  
        BitmapImage[] bmp = new BitmapImage[8];  
        bmp[0] = GetImageFromBytes(System.IO.File.ReadAllBytes(System.Windows.Forms.Application.StartupPath + @"\Images\Add.bin"));  
        bmp[1] = GetImageFromBytes(System.IO.File.ReadAllBytes(System.Windows.Forms.Application.StartupPath + @"\Images\Close.bin"));  
        bmp[2] = GetImageFromBytes(System.IO.File.ReadAllBytes(System.Windows.Forms.Application.StartupPath + @"\Images\Copy.bin"));  
        bmp[3] = GetImageFromBytes(System.IO.File.ReadAllBytes(System.Windows.Forms.Application.StartupPath + @"\Images\Cut.bin"));  
        bmp[4] = GetImageFromBytes(System.IO.File.ReadAllBytes(System.Windows.Forms.Application.StartupPath + @"\Images\Delete.bin"));  
        bmp[5] = GetImageFromBytes(System.IO.File.ReadAllBytes(System.Windows.Forms.Application.StartupPath + @"\Images\Edit.bin"));  
        bmp[6] = GetImageFromBytes(System.IO.File.ReadAllBytes(System.Windows.Forms.Application.StartupPath + @"\Images\Minimize.bin"));  
        bmp[7] = GetImageFromBytes(System.IO.File.ReadAllBytes(System.Windows.Forms.Application.StartupPath + @"\Images\Paste.bin"));  
        Add_Button.Content = bmp[0];  
        CloseIconImage.Source = bmp[1];  
        CopyMenuItem.Icon = bmp[2];  
        CutMenuItem.Icon = bmp[3];  
        Delete_Button.Content = bmp[4];  
        Edit_Button.Content = bmp[5];  
        MinimizeIconImage.Source = bmp[6];  
        PasteMenuItem.Icon = bmp[7];  
    }  

I use the following method to convert a binary image to a bitmap image ( this method works properly in other cases ):

    private BitmapImage GetImageFromBytes(byte[] bytes)  
    {  
        System.IO.MemoryStream Stream = new System.IO.MemoryStream();  
        Stream.Write(bytes, 0, bytes.Length);  
        Stream.Position = 0;  
        System.Drawing.Image img = System.Drawing.Image.FromStream(Stream);  
        BitmapImage bitImage = new BitmapImage();  
        bitImage.BeginInit();  
        System.IO.MemoryStream MS = new System.IO.MemoryStream();  
        img.Save(MS, System.Drawing.Imaging.ImageFormat.Png);  
        MS.Seek(0, System.IO.SeekOrigin.Begin);  
        bitImage.StreamSource = MS;  
        bitImage.EndInit();  
        return bitImage;  
    }  

But the output is as follows:
173478-context-menu.png
I think the problem is with the XAML code.

Thanks

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,663 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,173 questions
XAML
XAML
A language based on Extensible Markup Language (XML) that enables developers to specify a hierarchy of objects with a set of properties and logic.
760 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. رضا جافری 1,291 Reputation points
    2022-02-11T22:35:54.987+00:00

    I found the solution:
    We must use System.Windows.Controls.Image as follows:

        CopyMenuItem.Icon = new System.Windows.Controls.Image() { Source = bmp[2] };  
    

    So, I changed my C# codes:

        public AuthenticationWindow()  
        {  
            InitializeComponent();  
            ContextMenu CustomContextMenu = this.Resources["CustomContextMenu"] as ContextMenu;  
            MenuItem CopyMenuItem = CustomContextMenu.Items[0] as MenuItem;  
            MenuItem CutMenuItem = CustomContextMenu.Items[1] as MenuItem;  
            MenuItem PasteMenuItem = CustomContextMenu.Items[2] as MenuItem;  
            BitmapImage[] bmp = new BitmapImage[8];  
            bmp[0] = GetImageFromBytes(System.IO.File.ReadAllBytes(System.Windows.Forms.Application.StartupPath + @"\Images\Add.bin"));  
            bmp[1] = GetImageFromBytes(System.IO.File.ReadAllBytes(System.Windows.Forms.Application.StartupPath + @"\Images\Close.bin"));  
            bmp[2] = GetImageFromBytes(System.IO.File.ReadAllBytes(System.Windows.Forms.Application.StartupPath + @"\Images\Copy.bin"));  
            bmp[3] = GetImageFromBytes(System.IO.File.ReadAllBytes(System.Windows.Forms.Application.StartupPath + @"\Images\Cut.bin"));  
            bmp[4] = GetImageFromBytes(System.IO.File.ReadAllBytes(System.Windows.Forms.Application.StartupPath + @"\Images\Delete.bin"));  
            bmp[5] = GetImageFromBytes(System.IO.File.ReadAllBytes(System.Windows.Forms.Application.StartupPath + @"\Images\Edit.bin"));  
            bmp[6] = GetImageFromBytes(System.IO.File.ReadAllBytes(System.Windows.Forms.Application.StartupPath + @"\Images\Minimize.bin"));  
            bmp[7] = GetImageFromBytes(System.IO.File.ReadAllBytes(System.Windows.Forms.Application.StartupPath + @"\Images\Paste.bin"));  
            Add_Button.Content = bmp[0];  
            CloseIconImage.Source = bmp[1];  
            CopyMenuItem.Icon = new System.Windows.Controls.Image() { Source = bmp[2] };  
            CutMenuItem.Icon = new System.Windows.Controls.Image() { Source = bmp[3]};  
            Delete_Button.Content = bmp[4];  
            Edit_Button.Content = bmp[5];  
            MinimizeIconImage.Source = bmp[6];  
            PasteMenuItem.Icon = new System.Windows.Controls.Image() { Source = bmp[7] };  
        }  
    

    Output:
    173694-output.gif
    Thanks

    0 comments No comments