I'm currently working on a small C# Project to visualize our seating order in the Office. As we have multiple, different rooms, the desk layout is created dynamically. The data comes from an XML where a jpg-image (room layout) is stored as a base64 encoded string. Moreover, the XML file contains a list of all desks with their absolute pixel-Position on the Image.
Until now, I managed to draw the different room-images, each into a seperate tab page and all the desks (which are stored in a List of a "desk"-object.) at their position on the Image. All this is done in the xaml-file of the window.
My Problem is now that the canvas does not size the children, i.e. Image and desks, according to the parent's (i.e. tab page's) size.
I already tried using a grid oder putting a viewbox aroud the canvas and writing a custom canvas class by overriding the MeasureOverride() function.
Here is a minimal working example of my xaml file:
<TabControl x:Name="tabControl" Grid.Column="0">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<Canvas>
<Image
Source="{Binding Image}" >
</Image>
<ItemsControl ItemsSource="{Binding Docks}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border
Height="34"
BorderThickness="1"
Tag="{Binding Self}"
>
<TextBlock
Text="{Binding Caption}"
RenderTransformOrigin="0.5,0.5"
Width="{Binding DockWidth}"
TextAlignment="Center"
VerticalAlignment="Center"
TextWrapping="Wrap"
>
</TextBlock>
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform X="{Binding Position.Item1}" Y="{Binding Position.Item2}"/>
</TransformGroup>
</Border.RenderTransform>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Canvas>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
Does anybody have an idea what I can do? I'm not bound to a canvas. If there is another good way to do the Job, just let me know.
Viewbox should work. For example this will resize correctly (if you have jpeg with 96 dpi, if no, I think you'll have to recalculate canvas sizes):
<Grid HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Viewbox Stretch="Fill"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Canvas Width="{Binding ElementName=img, Path=ActualWidth}"
Height="{Binding ElementName=img, Path=ActualHeight}">
<Image Name="img"
Source="pack://siteoforigin:,,,/images/img1.jpg" />
<Canvas Canvas.Left="100"
Canvas.Top="50">
<Rectangle Width="50"
Height="100"
Fill="Beige" />
<TextBlock Text="AAA" />
</Canvas>
</Canvas>
</Viewbox>
</Grid>
Related
*The code below is fine, the issue was elsewhere - leaving here incase others need the info.
I am creating a simulator that has a large scrollable-zoomable Canvas. I need to be to place a StackPanel (or whatever) on top of this canvas, but it should not scroll or zoom. This is what I've got:
<Grid>
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Label Content="{Binding Date, StringFormat=Date: {0}}"/>
<Label Content="{Binding CO2Level}"/>
<Label Content="{Binding O2Level}"/>
<Label Content="{Binding H2OLevels}"/>
<Label Content="{Binding TempC}"/>
<Label Content="{Binding TempF}"/>
<Label Content="{Binding SolarLevels}"/>
</StackPanel>
<ScrollViewer Name="scrollViewer" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible">
<Grid Name="grid" Width="65535" Height="65535" RenderTransformOrigin="0.5, 0.5">
<Grid.LayoutTransform>
<TransformGroup>
<ScaleTransform x:Name="scaleTransform"/>
</TransformGroup>
</Grid.LayoutTransform>
<Canvas x:Name="canvas" HorizontalAlignment="Center" VerticalAlignment="Center"
Width="0" Height="0" RenderTransform="1 0 0 -1 0 0">
<!-- Setup automatic viewing of Lifeforms -->
<ItemsControl ItemsSource="{Binding Entities}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Path Data="{Binding Geometry}"
Fill="{Binding Fill}"
StrokeThickness="0"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Canvas>
</Grid>
</ScrollViewer>
</Grid>
However it is not working, the lebels do not show up at all and I cannot figure out how to do this. Any ideas?
If only one image is added to the database that my View is binded to, my WP8 app will display the whole image. If I add another image to the database, it will display both images, but the second one is overlapping the bottom of the first. Is there a way to add a gap between them so this doesn't happen?
Here is the xaml:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox x:Name="MainLongListSelector" Margin="0,0,-12,0" ItemsSource="{Binding Images}" SelectionChanged="MainLongListSelector_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="14,5,4,10">
<!--<Image Width="200" Source="HappyDragon.jpg"/>-->
<!--<Image x:Name="OutputImage" />-->
<Image x:Name="img" Source="{Binding ImageData, Converter={StaticResource ImageConverter}}"
MaxWidth="250" MaxHeight="300" Margin="10,10,0,10" RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<RotateTransform x:Name="ImageRotate" Angle="90" />
</Image.RenderTransform>
</Image>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
Try this one,
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox x:Name="MainLongListSelector" Height="300" Margin="0,0,-12,0" ItemsSource="{Binding Images}" SelectionChanged="MainLongListSelector_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="14,5,4,10">
<!--<Image Width="200" Source="HappyDragon.jpg"/>-->
<!--<Image x:Name="OutputImage" />-->
<Image x:Name="img" Source="{Binding ImageData, Converter={StaticResource ImageConverter}}"
MaxWidth="250" MaxHeight="300" Margin="10,30,0,20" RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<RotateTransform x:Name="ImageRotate" Angle="90" />
</Image.RenderTransform>
</Image>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
im trying to achieve something looking like this using a GridView in a Windows Store App project
i can get my items in a single line with horizontal scroll, but i want to have a GridView with 2 rows.
<GridView Grid.Row="1" Margin="22,0,0,0" Style="{StaticResource GridViewStyle}" SelectionMode="None" ItemsSource="{Binding UserPhotos}" HorizontalContentAlignment="Center" VerticalContentAlignment="Center">
<GridView.ItemTemplate>
<DataTemplate>
<Ellipse HorizontalAlignment="Left" Height="30" Width="30" Margin="0,7,10,0">
<Ellipse.Fill>
<ImageBrush Stretch="Uniform" ImageSource="{Binding}"/>
</Ellipse.Fill>
</Ellipse>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
what should i change/add to get this result?
I have to say that is not really intuitive and the default behavior is usually vertical for the scrollviewer, here is the solution:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ScrollViewer VerticalScrollBarVisibility="Hidden" VerticalScrollMode="Disabled" HorizontalScrollBarVisibility="Auto" HorizontalScrollMode="Enabled">
<GridView Grid.Row="1" Margin="22,0,0,0" SelectionMode="None" HorizontalContentAlignment="Center" VerticalContentAlignment="Center">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Vertical" MaximumRowsOrColumns="2"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<DataTemplate>
<Grid>
<Ellipse Stroke="Black" Width="144" Height="144"></Ellipse>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding}"/>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.Items>
<x:String>1</x:String>
<x:String>2</x:String>
<x:String>3</x:String>
<x:String>4</x:String>
<x:String>5</x:String>
<x:String>6</x:String>
<x:String>7</x:String>
<x:String>8</x:String>
<x:String>9</x:String>
<x:String>10</x:String>
<x:String>11</x:String>
<x:String>12</x:String>
<x:String>13</x:String>
<x:String>14</x:String>
</GridView.Items>
</GridView>
Replace with your template and itemssource as you had
I have an collection of images that I am painting on a canvas control. I want to be able to mask and unmask parts of the canvas in real-time.
I was thinking of using a WritableBitmap for the source of the opacity mask, but WritableBitmaps are limited to drawing with a 1-pixel brush (cant change the stroke thickness).
I am able to paint on another canvas the desired opacity mask, however I would have to constantly render that canvas to an imagesource, which is super slow.
There must be a simple way.
Edit - Some details of my app:
I am creating a painting app. I draw a collection of images onto a canvas. I have a collection of these canvases (to simulate a layer system), each with their own collection of images. So I am trying to implement a feature to edit the opacity mask of each canvas (each layer) on the fly.
Here is the collection of collections code behind
<!--Outer collection-->
<ItemsControl Name="canvasDataBinding"
Focusable="True"
HorizontalAlignment="Center"
Height="512"
Width="512"
VerticalAlignment="Center"
ClipToBounds="True">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas MouseMove="Canvas_MouseMove"
MouseEnter="Canvas_MouseEnter"
MouseLeave="Canvas_MouseLeave"
MouseDown="Canvas_MouseDown"
MouseUp="Canvas_MouseUp"
Background="Transparent">
</Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!--nested collection-->
<ItemsControl Height="512" Width="512" HorizontalAlignment="Center" VerticalAlignment="Center" ItemsSource="{Binding ImageSource}" OpacityMask="{Binding Mask}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Transparent"
Height="512"
Width="512"
HorizontalAlignment="Center"
VerticalAlignment="Center">
</Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Source="{Binding Name}"
Width="{Binding Width}"
Height="{Binding Height}"
Opacity="{Binding Opacity}">
<Image.RenderTransform>
<TransformGroup>
<TranslateTransform X="{Binding OffsetX}" Y="{Binding OffsetY}"/>
<RotateTransform CenterX="{Binding CenterX}" CenterY="{Binding CenterY}" Angle="{Binding Angle}"/>
</TransformGroup>
</Image.RenderTransform>
</Image>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I have this xaml code of my metro app.
<Grid Width="531" Height="531">
<Grid.Background>
<ImageBrush ImageSource="{Binding image1}" Stretch="UniformToFill" />
</Grid.Background>
<StackPanel Background="#0072B0" Opacity="0.7" VerticalAlignment="Bottom">
<Border BorderThickness="0,0,0,1" BorderBrush="White">
<TextBlock Text="{Binding name}" VerticalAlignment="Bottom" Opacity="1" Style="{StaticResource BigTopDealItemTitle}"/>
</Border>
</StackPanel>
</Grid>
I wanna make a blur panel and clear text on it. But look like the text in TextBlock blur too, even I set Opacity of it with 1.
To make a background blurry without making the textbox blurry do something like this:
<Grid Width="531" Height="531">
<Grid.Background>
<ImageBrush ImageSource="{Binding image1}" Stretch="UniformToFill" />
</Grid.Background>
<StackPanel Background="#0072B0" Opacity="0.7" VerticalAlignment="Bottom">
<Grid>
<Border BorderThickness="0,0,0,1" BorderBrush="White"/>
<TextBlock Text="{Binding name}" VerticalAlignment="Bottom" Style="{StaticResource BigTopDealItemTitle}"/>
</Grid>
</StackPanel>
</Grid>
This will put the TextBlock on top of the background (i.e. the Border) without it being affected by the properties of the Border.