Canvas ImageSource not showing image - c#

Here is my xaml:
<StackPanel Height="333">
<Canvas x:Name="imageCanvas"
RenderOptions.BitmapScalingMode="NearestNeighbor"
RenderOptions.EdgeMode="Aliased">
<Canvas.Background>
<ImageBrush x:Name="image1"
Stretch="None"
AlignmentX="Left"
AlignmentY="Top">
</ImageBrush>
</Canvas.Background>
</Canvas>
<Canvas x:Name="overlayCanvas">
<Rectangle Name="dummyRectangle" Width="1" Height="2" Fill="Transparent" />
</Canvas>
</StackPanel>
Here is my C# code behind:
void PlayImages()
{
string testImageFolder = "C:\\TestImages";
DirectoryInfo d = new DirectoryInfo(testImageFolder);//Assuming Test is your Folder
FileInfo[] Files = d.GetFiles("*.tif"); //Getting Text files
image1.ImageSource = new BitmapImage(new Uri("C:\\TestImages\\ChanA_0001_0001_0001_0001.tif"));
}
However, when the C# code above executed, nothing happened on UI. I am wondering where should I change to make the image show up? Thanks.

It was the stack panel that causes the problem. I am not sure why, but if some of them are removed, then the image shows up. The xaml with some stack penal removed is like following:
<StackPanel HorizontalAlignment="Left">
<!--Controls:MenuControl/-->
<Controls:ToggleButtonControl Margin="0,0,0,0" Height="43" RenderTransformOrigin="0.5,-0.233" />
</StackPanel>
<Canvas x:Name="imageCanvas"
RenderOptions.BitmapScalingMode="NearestNeighbor"
RenderOptions.EdgeMode="Aliased" Margin="0,52,0,0">
<Canvas.Background>
<ImageBrush x:Name="image1"
Stretch="None"
AlignmentX="Left"
AlignmentY="Top"
ImageSource="{Binding Path=Bitmap, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
</ImageBrush>
</Canvas.Background>
</Canvas>

Your imageCanvas always has width and height zero, because you neither add any children, not set its Width or Height explicitly.
Change your XAML to use only one Canvas instead, and optionally (depending on the outer container and the children to be added) set its Width and Height properties:
<Canvas x:Name="overlayCanvas" Height="333" Width="500">
<Canvas.Background>
<ImageBrush x:Name="image1" ... />
</Canvas.Background>
<Rectangle ... />
</Canvas>

Related

Display icon over select images in wpf listbox

I've looked at some related answers (Content of a Button Style appears only in one Button instance, and Images only showing in last ListBoxItem), but can't seem to get their answers to work in my example.
My app wpf stack is relatively complex.
I've a UserControl within another window. Within the UserControl, I've a ListBox with nested elements ListBox.ItemTemplate > DataTemplate > Border > Grid > StackPanel
Within the StackPanel is a TextBlock, followed by an Image and a StackPanel.ToolTip
I'm wanting to place an icon over the Image, so I've further obfuscated the image by putting it in a Grid, and adding a ViewBox accessed via a Control Template (as suggested in the above links), so that the ViewBox is centered on the image. Here's the Grid:
<Grid>
<Image RenderOptions.BitmapScalingMode="HighQuality"
Height="{Binding ElementName=_this, Path=ThumbSize.Height}"
>
<gif:ImageBehavior.AnimatedSource>
<MultiBinding Converter="{c:ImageConverter}">
<Binding Path="ThumbLocation" />
<Binding Path="FullName" />
</MultiBinding>
</gif:ImageBehavior.AnimatedSource>
</Image>
<Control Template="{StaticResource PlaySymbol}" Visibility="{Binding PlayVisible}" />
</Grid>
The ViewBox's ControlTemplate is in the UserControl.Resources up at the top
<ControlTemplate x:Key="PlaySymbol" TargetType="{x:Type Control}">
<Viewbox Stretch="Uniform"
RenderTransformOrigin="0.5,0.5"
Opacity="0.75"
x:Shared="False"
>
<Viewbox.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="0.5" ScaleY="0.5"/>
</TransformGroup>
</Viewbox.RenderTransform>
<ContentControl Content="{StaticResource appbar_control_play}" />
</Viewbox>
</ControlTemplate>
The appbar_control_play is in the Resources directory in an Icons.xaml file.
<Canvas x:Key="appbar_control_play" Width="76" Height="76" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
<Path Width="20.5832" Height="31.6667" Canvas.Left="30.0833" Canvas.Top="22.1667" Stretch="Fill" Fill="{DynamicResource BlackBrush}" Data="F1 M 30.0833,22.1667L 50.6665,37.6043L 50.6665,38.7918L 30.0833,53.8333L 30.0833,22.1667 Z "/>
</Canvas>
The goal is to only display the icon for 'play' on movies. I've set the PlayVisible to return the proper visibility for movies, and not for other files. Yet, it is only displaying for the last movie. I've heard that this is the case for controls only able to have one parent. I've tried setting x:Shared="False" on the ViewBox, but to no avail.
The app works, but I've recently decided to add movies to the listing and want to display the play icon over their thumbnails, but not the other items. It seems simple on the outset, but I've yet to figure out what is needed.
Any help would be appreciated, otherwise I feel I may have to resort to overlaying the icon on the actual thumbnails of the movies.
It looks like the problem is not related to the Viewbox but the image resource appbar_control_play it references.
There is no need to add the Viewbox via a Control. Just add it directly to the DataTemplate.
Generally prefer a ContentControl over a templated Control if you wish to display content.
The x:Shared attribute is only required on a UIElement that is not part of a template but defined in a ResourceDictionary. For example, when you define the Viewbox in as a resource, you must set the x:Shared attribute to false. Otherwise it is only allowed to appear once in the visual tree.
In case the image resource is an image file, a proper DataTemplate could look as followed:
<DataTemplate>
<StackPanel>
<Grid>
<Image Source="path to image" />
<Image Source="path to overlay icon"
Stretch="UniformToFill"
Width="50"
Height="50" />
</Grid>
</StackPanel>
</DataTemplate>
In case the icon is a XAML resource like a Geometry or a Segoe MDL2 Assets font icon, the DataTemplate should look as followed:
App.xaml
<Application.Resources>
<Viewbox x:Key="PlayIcon" x:Shared="False">
<TextBlock FontFamily="Segoe MDL2 Assets"
Text="" />
</Viewbox>
<Viewbox x:Key="appbar_control_play"
x:Shared="False">
<Path Width="20.5832"
Height="31.6667"
Stretch="Fill"
Fill="{Binding RelativeSource={RelativeSource AncestroType=ContentControl}, Path=For4ground}"
Data="F1 M 30.0833,22.1667L 50.6665,37.6043L 50.6665,38.7918L 30.0833,53.8333L 30.0833,22.1667 Z " />
</Viewbox>
</Application.Resources>
MyControl.xaml
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Grid>
<Image Source="path to image" />
<ContentControl Content="{StaticResource appbar_control_play}"
Width="50"
Height="50"
Foreground="Pink" />
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
Not sure what's happening on your side but the following just works:
<Window x:Class="abc.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:system="clr-namespace:System;assembly=System.Runtime"
mc:Ignorable="d"
Title="Window1">
<Grid>
<ListBox>
<ListBox.ItemTemplate>
<DataTemplate>
<DataTemplate.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</DataTemplate.Resources>
<Border Width="64" Height="64" BorderBrush="Red" BorderThickness="1">
<Grid>
<TextBlock Text="{Binding}"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
<Rectangle Fill="DeepSkyBlue"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="2"
Width="16"
Height="16"
Visibility="{Binding Converter={StaticResource BooleanToVisibilityConverter}}"
x:Name="Button" />
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
<system:Boolean>True</system:Boolean>
<system:Boolean>False</system:Boolean>
<system:Boolean>True</system:Boolean>
<system:Boolean>False</system:Boolean>
<system:Boolean>True</system:Boolean>
<system:Boolean>False</system:Boolean>
</ListBox>
</Grid>
</Window>

Crop content of rounded-corner border with image out of border

I need to move and rotate the image outside of the rounded border
example:
In How to make the contents of a round-cornered border be also round-cornered? find answer:
<Grid>
<Grid.OpacityMask>
<VisualBrush Visual="{Binding ElementName=Border1}" />
</Grid.OpacityMask>
<Border x:Name="Border1" CornerRadius="30" Background="Green" />
<TextBlock Text="asdas das d asd a sd a sda" />
</Grid>
This works if the elements do not go out of bounds.
If using rotate and/or margin like this:
<Grid>
<Grid.OpacityMask>
<VisualBrush Visual="{Binding ElementName=_border1}" />
</Grid.OpacityMask>
<Border x:Name="_border1"
BorderThickness="0"
CornerRadius="30"
Background="Green" />
<TextBlock Text="SomeText"
Foreground="Yellow" />
<Image Source="https://ssl.gstatic.com/ui/v1/icons/mail/rfr/logo_gmail_lockup_default_1x_r2.png"
Margin="-5 0 0 0"
Height="20"
Width="55"
Stretch="UniformToFill"
VerticalAlignment="Top"
HorizontalAlignment="Left"
RenderTransformOrigin="0.5 0.5">
<Image.RenderTransform>
<RotateTransform Angle="-7" />
</Image.RenderTransform>
</Image>
</Grid>
The rounding is displaced
How can I crop the image like in the first example? Thanks for your help.
Something is going wrong with the viewport calculation of the VisualBrush. Not sure if that is a bug in WPF.
A workaround could be setting the viewport in absolute units, with Rectangle instead of a Border:
<Grid.OpacityMask>
<VisualBrush
Visual="{Binding ElementName=rect}"
ViewportUnits="Absolute"
Viewport="{Binding ElementName=rect, Path=RenderedGeometry.Rect}"/>
</Grid.OpacityMask>
<Rectangle x:Name="rect" RadiusX="30" RadiusY="30" Fill="Green"/>
Or simpler, with setting the Clip property instead of OpacityMask, but still supporting resize:
<Grid Clip="{Binding ElementName=rect, Path=RenderedGeometry}">
<Rectangle RadiusX="30" RadiusY="30" Fill="Green" x:Name="rect"/>
...
</Grid>
I managed to achieve the desired result using Clip instead of OpacityMask. Then all the elements that need to be cropped must be children of the Border. If your Border needs to be dynamic, you need to bind the dimensions of the RectangleGeometry to the dimensions of the Border using Converter.
<Grid>
<Border BorderThickness="0"
CornerRadius="30"
Background="Green">
<Border.Clip>
<RectangleGeometry RadiusX="30" RadiusY="30" Rect="0,0,500,400"/>
</Border.Clip>
<Grid>
<TextBlock Text="SomeText"
Foreground="Yellow"/>
<Image Source="https://ssl.gstatic.com/ui/v1/icons/mail/rfr/logo_gmail_lockup_default_1x_r2.png"
Margin="-5 0 0 0"
Height="20"
Width="55"
Stretch="UniformToFill"
VerticalAlignment="Top"
HorizontalAlignment="Left"
RenderTransformOrigin="0.5 0.5">
<Image.RenderTransform>
<RotateTransform Angle="-7"/>
</Image.RenderTransform>
</Image>
</Grid>
</Border>
</Grid>

How can I copy a Region of Interest into an image in WPF? [duplicate]

I want to show a specific area of an image in my WPF control.
Let's say the original image dimensions are 600x400 and I'm trying to show a rectangle inside that image, positioned on X=420,Y=330 with width=60, height=40.
So I tried to use ScaleTransform and calculate the scale factor as 10, and the RenderTransformOrigin to 0.75, 0.85.
But when I view the control I don't get the image I expected. (only the red rectangle).
The is the code:
<Grid>
<Button Width="600" Height="400">
<Button.Template>
<ControlTemplate>
<Grid ClipToBounds="True">
<Image Source="c:\temp\sample.bmp" Stretch="Uniform" RenderTransformOrigin="0.75, 0.85">
<Image.RenderTransform>
<ScaleTransform ScaleX="10" ScaleY="10" />
</Image.RenderTransform>
</Image>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
That the result:
You could use a CroppedBitmap:
<Image>
<Image.Source>
<CroppedBitmap Source="c:\temp\sample.bmp" SourceRect="420,330,60,40"/>
</Image.Source>
</Image>
Or you use an ImageBrush with an appropriate Viewbox:
<Grid>
<Grid.Background>
<ImageBrush ImageSource="c:\temp\sample.bmp"
ViewboxUnits="Absolute" Viewbox="420,330,60,40"/>
</Grid.Background>
</Grid>

How to use the XAML dictionary that Syncfusion Metro Studio produces

For resolution independence we want scaling art. Ok, so a common source for that mentioned on stack is Syncfusion Metro Studio.
Metro Studio 2 produces this for XAML:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Viewbox x:Key="error">
<Grid Width="64" Height="64" Visibility="Visible">
<Grid Visibility="Visible">
<Rectangle Fill="#FFD21818" Visibility="Visible" />
<Ellipse Fill="#FFD21818" Visibility="Collapsed" />
<Path Data="M50.5,4.7500001C25.232973,4.75 4.75,25.232973 4.7500001,50.5 4.75,75.767029 25.232973,96.25 50.5,96.25 75.767029,96.25 96.25,75.767029 96.25,50.5 96.25,25.232973 75.767029,4.75 50.5,4.7500001z M50.5,0C78.390381,0 101,22.609621 101,50.5 101,78.390381 78.390381,101 50.5,101 22.609621,101 0,78.390381 0,50.5 0,22.609621 22.609621,0 50.5,0z" Stretch="Fill" Fill="#FFD21818" Visibility="Collapsed" />
</Grid>
<Path Data="F1M54.0573,47.8776L38.1771,31.9974 54.0547,16.1198C55.7604,14.4141 55.7604,11.6511 54.0573,9.94531 52.3516,8.23962 49.5859,8.23962 47.8802,9.94531L32.0026,25.8229 16.1224,9.94531C14.4167,8.23962 11.6511,8.23962 9.94794,9.94531 8.24219,11.6511 8.24219,14.4141 9.94794,16.1198L25.8255,32 9.94794,47.8776C8.24219,49.5834 8.24219,52.3477 9.94794,54.0534 11.6511,55.7572 14.4167,55.7585 16.1224,54.0534L32.0026,38.1745 47.8802,54.0534C49.5859,55.7585 52.3516,55.7572 54.0573,54.0534 55.7604,52.3477 55.763,49.5834 54.0573,47.8776z" Stretch="Uniform" Fill="#FFFFFFFF" Width="36" Height="36" Margin="0,0,0,0" RenderTransformOrigin="0.5,0.5">
<Path.RenderTransform>
<TransformGroup>
<TransformGroup.Children>
<RotateTransform Angle="0" />
<ScaleTransform ScaleX="1" ScaleY="1" />
</TransformGroup.Children>
</TransformGroup>
</Path.RenderTransform>
</Path>
</Grid>
</Viewbox>
</ResourceDictionary>
So far so good, just merge this into the project resources. But how to consume this?
using viewbox in ResourceDictionary file has an answer that lets you change the ViewBox to DataTemplate in the ResourceDictionary and then use a converter to display it as a button's ContentTemplate. That is ok for Button based stuff, but what if I just need the icon itself. How do I go from ViewBox in a resource dictionary to somehow including it in lets say a grid in XAML?
You can use it as Content for any ContentControl Directly,in case if you just want the icon in Grid,try like below,
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Viewbox x:Key="error">
<Grid Width="64" Height="64" Visibility="Visible">
<Grid Visibility="Visible">
<Rectangle Fill="#FFD21818" Visibility="Visible" />
<Ellipse Fill="#FFD21818" Visibility="Collapsed" />
<Path Data="M50.5,4.7500001C25.232973,4.75 4.75,25.232973 4.7500001,50.5 4.75,75.767029 25.232973,96.25 50.5,96.25 75.767029,96.25 96.25,75.767029 96.25,50.5 96.25,25.232973 75.767029,4.75 50.5,4.7500001z M50.5,0C78.390381,0 101,22.609621 101,50.5 101,78.390381 78.390381,101 50.5,101 22.609621,101 0,78.390381 0,50.5 0,22.609621 22.609621,0 50.5,0z" Stretch="Fill" Fill="#FFD21818" Visibility="Collapsed" />
</Grid>
<Path Data="F1M54.0573,47.8776L38.1771,31.9974 54.0547,16.1198C55.7604,14.4141 55.7604,11.6511 54.0573,9.94531 52.3516,8.23962 49.5859,8.23962 47.8802,9.94531L32.0026,25.8229 16.1224,9.94531C14.4167,8.23962 11.6511,8.23962 9.94794,9.94531 8.24219,11.6511 8.24219,14.4141 9.94794,16.1198L25.8255,32 9.94794,47.8776C8.24219,49.5834 8.24219,52.3477 9.94794,54.0534 11.6511,55.7572 14.4167,55.7585 16.1224,54.0534L32.0026,38.1745 47.8802,54.0534C49.5859,55.7585 52.3516,55.7572 54.0573,54.0534 55.7604,52.3477 55.763,49.5834 54.0573,47.8776z" Stretch="Uniform" Fill="#FFFFFFFF" Width="36" Height="36" Margin="0,0,0,0" RenderTransformOrigin="0.5,0.5">
<Path.RenderTransform>
<TransformGroup>
<TransformGroup.Children>
<RotateTransform Angle="0" />
<ScaleTransform ScaleX="1" ScaleY="1" />
</TransformGroup.Children>
</TransformGroup>
</Path.RenderTransform>
</Path>
</Grid>
</Viewbox>
</ResourceDictionary>
<Grid>
<ContentControl Content="{StaticResource error}"/>
</Grid>
if you are intend to use the same resource in multiple location,please set x:Shared attribute as false as below,
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Viewbox x:shared="false" x:Key="error">
.......
</Viewbox>
</ResourceDictionary>
I did a similar thing in one of my projects using Syncfusion Metro Studio. I found wrapping the image in a ViewBox caused a number of annoyances. I ended up using the image alone, and then embedded it into a Path where I wanted to use the image.
I found it a lot more flexible than trying to squeeze a ViewBox into xaml.
How I did it:
There is a type Geometry, which allows you to define a Bezier path as a resource:
<Geometry x:Key="Keyboard">M48.537998,24.254L57.365002,24.254 57.365002,30.875 48.537998,30.875z M17.642,24.254L46.332001,24.254 46.332001,30.875 17.642,30.875z M6.6760006,24.254L15.504,24.254 15.504,30.875 6.6760006,30.875z M50.744999,15.426L57.365002,15.426 57.365002,22.047001 50.744999,22.047001z M41.986,15.426L48.606998,15.426 48.606998,22.047001 41.986,22.047001z M33.09,15.426L39.709999,15.426 39.709999,22.047001 33.09,22.047001z M24.261999,15.426L30.882999,15.426 30.882999,22.047001 24.261999,22.047001z M15.435,15.426L22.056,15.426 22.056,22.047001 15.435,22.047001z M6.6070004,15.426L13.229,15.426 13.229,22.047001 6.6070004,22.047001z M50.744999,6.599L57.365002,6.599 57.365002,13.219 50.744999,13.219z M41.986,6.599L48.606998,6.599 48.606998,13.219 41.986,13.219z M33.09,6.599L39.709999,6.599 39.709999,13.219 33.09,13.219z M24.261999,6.599L30.882999,6.599 30.882999,13.219 24.261999,13.219z M15.435,6.599L22.056,6.599 22.056,13.219 15.435,13.219z M6.6070004,6.599L13.229,6.599 13.229,13.219 6.6070004,13.219z M4.47015,4.4635506L4.47015,33.242199 59.6413,33.242199 59.6413,4.4635506z M1.3333101,0L62.666698,0C63.403,0,64,0.59634399,64,1.3333397L64,36.166698C64,36.903702,63.403,37.5,62.666698,37.5L1.3333101,37.5C0.59704602,37.5,0,36.903702,0,36.166698L0,1.3333397C0,0.59634399,0.59704602,0,1.3333101,0z</Geometry>
Once you have a geometry resource you can use it in Path.Data. In this example the border is the bounds of the image 32x32 pixels. Then you can use the Border and use it in a Grid as you would with any other control.
<Border Width="32" Height="32">
<Path Data="{StaticResource Keyboard}" Fill="White" Stretch="Uniform" RenderTransformOrigin="0.5, 0.5">
</Path>
</Border>
This technique also allows you to bind the properties as needed. I.e. Fill to a color, and have it change dynamically.
Simply import the output from Metro Studio into Expression Blend
-> Design View
Select icon and click 'Tools' -> Make Brush Resource -> MakeDrawingBrush
Then Blend will convert the icon for use anywhere in your app

cannot draw shape in canvas

I have a canvas in xaml defined as following. However adding a rectangle in it doesn't show any thing.
<lib:DrawingCanvas x:Name="drawingCanvas" Background="White" AllowDrop="True">
<Rectangle Margin="20,20,20,20" Fill="Black" Stroke="White" Width="100" Height="100">
</Rectangle>
</lib:DrawingCanvas>
Can you give me some hints here?
Thanks.
You're not using a Canvas, you're using a "DrawingCanvas", so I can't speak for any differences. But assuming it derives from Canvas:
You need to set the attached properties for the Rectangle. These are Canvas.Left or Canvas.Right, in addition to Canvas.Top or Canvas.Bottom.
For example:
<Rectangle Canvas.Left="50" Canvas.Top="100" Width="100" Height="100" Fill="Black" />

Categories

Resources