UserControl with Bounding Box Scaling Point boxes - c#

I want to make a UserControl like this image;
There are 9 boxes, top one is for rotating, while other one is for scaling purposes. I tried to make this with grid and background image, 2 rows, and small boxes with StackPanel, but have to provide lots of negative and positive margins to achieve this result. Is there any easy way to do so need help.
Thanks.

Something like this?
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.Resources>
<Style TargetType="Rectangle">
<Setter Property="Stroke" Value="Black"/>
<Setter Property="StrokeThickness" Value="1"/>
<Setter Property="Height" Value="11"/>
<Setter Property="Width" Value="11"/>
<!-- For hittestvisibility -->
<Setter Property="Fill" Value="Transparent"/>
</Style>
</Grid.Resources>
<Line X1="0" Y1="1" X2="0" Y2="0" Stretch="Fill" Stroke="Black" />
<Rectangle VerticalAlignment="Top" HorizontalAlignment="Center"/>
<Grid Grid.Row="1" Height="200" Width="200" Margin="-5">
<Rectangle Margin="5" Height="Auto" Width="Auto" Fill="{x:Null}"/>
<Rectangle VerticalAlignment="Top" HorizontalAlignment="Left"/>
<Rectangle VerticalAlignment="Top" HorizontalAlignment="Center"/>
<Rectangle VerticalAlignment="Top" HorizontalAlignment="Right"/>
<Rectangle VerticalAlignment="Center" HorizontalAlignment="Left"/>
<Rectangle VerticalAlignment="Center" HorizontalAlignment="Right"/>
<Rectangle VerticalAlignment="Bottom" HorizontalAlignment="Left"/>
<Rectangle VerticalAlignment="Bottom" HorizontalAlignment="Center"/>
<Rectangle VerticalAlignment="Bottom" HorizontalAlignment="Right"/>
<!-- The Content -->
<Rectangle Width="Auto" Height="Auto" Margin="20" Fill="Green"/>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
Text="Content"/>
</Grid>
</Grid>
The terminology is Bounding Box

Related

Viewbox scales things too small at high resolutions and scale factors and they are virtually impossible to see

I have a grid with one row and some columns. In order to scale correctly the grid content according to the screen resolution and scale selected in the Windows OS, I use a Viewbox.
I also define a style that is applied to all Viewboxes:
<Style TargetType="{x:Type Viewbox}">
<Setter Property="Stretch" Value="Uniform"/>
<Setter Property="StretchDirection" Value="Both"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="OverridesDefaultStyle" Value="False"/>
<Setter Property="UseLayoutRounding" Value="False"/>
</Style>
And then I enclose every grid column within a Viewbox:
<Grid Focusable="True"
Height="Auto">
<Grid.ColumnDefinitions>
<!-- Animated image -->
<ColumnDefinition Width="Auto" />
<!-- Stack panel with icon and text -->
<ColumnDefinition Width="Auto" />
<!-- A vertical separator -->
<ColumnDefinition Width="Auto" />
<!-- A button -->
<ColumnDefinition Width="Auto" />
<!-- Empty dummy column to help distribute space correctly between columns so it will cause next columns to be horizontally right aligned. -->
<ColumnDefinition Width="*" />
<!-- Help button -->
<ColumnDefinition Width="Auto" />
<!-- Three dots button -->
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Viewbox Grid.Column="0">
<StackPanel Orientation="Horizontal"
Visibility="{Binding Path=IsAnimatedImgVisible, Converter={StaticResource BoolToVisibility}}">
<v:UserControlAnimatedImg x:Name="UcSpinner" VerticalAlignment="Center" HorizontalAlignment="Left"/>
<Label SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality"
VerticalAlignment="Center" HorizontalAlignment="Left"
Content="{Binding Path=StatusText}"/>
</StackPanel>
</Viewbox>
<Viewbox Grid.Column="1">
<StackPanel Orientation="Horizontal">
<Image
Margin="10,5"
Height="24"
Width="24"
MaxHeight="24"
MaxWidth="24"
VerticalAlignment="Center"
HorizontalAlignment="Center"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality"
Source="{Binding Path=Icon}"/>
<Label
VerticalAlignment="Center"
HorizontalAlignment="Left"
Content="{Binding Path=StatusTxt}"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality">
</Label>
</StackPanel>
</Viewbox>
<Viewbox Grid.Column="2">
<Separator Margin="10,5,5,5"
Height="26"
Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}">
</Viewbox>
<Viewbox Grid.Column="3">
<Button Height="Auto"
Width="150"
Command="{Binding ButtonOnClick}">
<StackPanel Orientation="Horizontal">
<Image
Height="24"
Width="25"
MaxHeight="24"
MaxWidth="25"
VerticalAlignment="Center"
HorizontalAlignment="Center"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality"
Source="{Binding ImageIcon}"/>
<TextBlock
Margin="10,2,5,2"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Text="{x:Static p:Resources.BtnText}"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality">
</TextBlock>
</StackPanel>
</Button>
</Viewbox>
<!-- Empty dummy space to help distribute space correctly between columns and
make next columns to be horizontally right aligned. This column will be blank
space.-->
<Viewbox Grid.Column="4">
<ContentControl />
</Viewbox>
<Viewbox Grid.Column="5">
<Button Height="25"
Width="25"
MaxHeight="25"
MaxWidth="25"
Margin="8,0,5,0"
Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"
Command="{Binding BtnHlpClick}">
<Image HorizontalAlignment="Center"
VerticalAlignment="Center"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality"
Source="{Binding ImageHelpIcon}"/>
</Button>
</Viewbox>
<Viewbox Grid.Column="6">
<StackPanel x:Name="PlaceHolder"
VerticalAlignment="Center"
Margin="2,0,12,0"
Width="27"
Height="Auto">
<Image HorizontalAlignment="Center"
VerticalAlignment="Center"
Height="20"
Width="20"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality"
Source="{Binding ImgThreeDotsIcon}">
<Image.ContextMenu>
<ContextMenu Placement="Bottom" Background="#FFFFFF">
<MenuItem Header="{x:Static p:Resources.mnutext}" Command="{Binding MenuOnClick}"></MenuItem>
</ContextMenu>
</Image.ContextMenu>
</Image>
</StackPanel>
</Viewbox>
The problem I am currently facing is that when I switch to high screen resolutions and also I switch to high scale factor (125%, 150%, 175%, 200%, and so on), then the content of the grid is getting smaller and smaller and it is practically impossible to see. The more screen resolution I select, the more smaller is the grid content. The more scale factor I select, the more smaller is the grid content. The problem is that the grid content gets too small and impossible to see.
How can I solve this?

Cant set 3 toggle button text content which use same style

i have three toggle buttons which use a singe style resource on wpf, now i cant set their content, content is declared more than once error, each toggle button has a different content.
Each toggle button uses an image as background also.
<UserControl.Resources>
<Style x:Key="Chromeless" TargetType="ToggleButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border BorderThickness="0" Width="197" Height="60">
<ContentPresenter TextElement.FontFamily="{TemplateBinding TextElement.FontFamily}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="0,0,0,0"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Image x:Key="page1Pressed" Source="/graph_engine;Component/cucaracha/LD3/button_1.png" Height="60" Width="197" />
<Image x:Key="page1" Source="/graph_engine;Component/cucaracha/LD3/button_1_pressed.png" Height="60" Width="197" />
<Image x:Key="page2Pressed" Source="/graph_engine;Component/cucaracha/LD3/button_2.png" Height="60" Width="197" />
<Image x:Key="page2" Source="/graph_engine;Component/cucaracha/LD3/button_2_pressed.png" Height="60" Width="197" />
<Image x:Key="page3Pressed" Source="/graph_engine;Component/cucaracha/LD3/button_3.png" Height="60" Width="197" />
<Image x:Key="page3" Source="/graph_engine;Component/cucaracha/LD3/button_3_pressed.png" Height="60" Width="197" />
</UserControl.Resources>
<Viewbox Stretch="Fill" StretchDirection="Both">
<Grid Height="60" Name="grid1" Width="591" Margin="0,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="197" />
<ColumnDefinition Width="197" />
<ColumnDefinition Width="197" />
</Grid.ColumnDefinitions>
<ToggleButton Style="{StaticResource Chromeless}" Name="page1" Background="Transparent" BorderBrush="Transparent" BorderThickness="0" Foreground="{x:Null}" Checked="page1_Checked" Unchecked="page1_Unchecked">
<DynamicResource ResourceKey="page1"/>
</ToggleButton>
<ToggleButton Grid.Column="1" Style="{StaticResource Chromeless}" Name="page2" Background="Transparent" BorderBrush="Transparent" BorderThickness="0" Foreground="{x:Null}" Unchecked="page2_Unchecked" Checked="page2_Checked">
<DynamicResource ResourceKey="page2"/>
</ToggleButton>
<ToggleButton Grid.Column="2" Style="{StaticResource Chromeless}" Name="page3" Background="Transparent" BorderBrush="Transparent" BorderThickness="0" Foreground="{x:Null}" Checked="page3_Checked" Unchecked="page3_Unchecked">
<DynamicResource ResourceKey="page3"/>
</ToggleButton>
</Grid>
</Viewbox>
Do you mean you can't change the image when you pressed down the toggle button? You only set a image to the content of toggle button. You can use Visual State Manager to change the background like this
If you just want to set the image and failed. Please check the image path.

xaml(wpf) How to address a control from my customwindow template?

I've created a customwindow template by redefining it, and inheriting from window. This template resides in a separate class library, and i build a dll and reference it from my main project.
This is a part of code from custom window xaml:
<!-- Window style -->
<Style TargetType="{x:Type local:CustomWindow}">
<Setter Property="WindowStyle" Value="None"/>
<Setter Property="ResizeMode" Value="NoResize"/>
<Setter Property="Background" Value="White"/>
<Setter Property="AllowsTransparency" Value="True"/>
<Setter Property="Opacity" Value="1" />
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="Silver"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomWindow}">
<Border BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}">
<Grid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Rectangle x:Name="moveRectangle" Fill="#24282A"
Grid.Row="0" Grid.Column="1"/>
<Label x:Name="WindowName" Background="#24282A" Foreground="White" Grid.Row="0" Grid.Column="0"/>
<StackPanel Grid.Row="0" Grid.Column="2" Orientation="Horizontal" Background="#24282A">
<Button x:Name="minimizeButton" Style="{StaticResource WindowButtonStyle}"
Content="0" />
<Button x:Name="restoreButton" Style="{StaticResource WindowButtonStyle}"
Content="1" />
<Button x:Name="closeButton" Style="{StaticResource WindowButtonStyle}"
Content="r" />
</StackPanel>
<Grid Background="#24282A" Opacity="0.9"
Grid.Row="1" Grid.ColumnSpan="3" Margin="5,0,5,5">
<AdornerDecorator>
<ContentPresenter/>
</AdornerDecorator>
</Grid>
</Grid>
<Grid x:Name="resizeGrid">
<Rectangle
Stroke="{x:Null}"
Fill="#24282A"
VerticalAlignment="Top"
Height="5"
x:Name="top"
Margin="5,0,5,0" />
<Rectangle
Stroke="{x:Null}"
Fill="#24282A"
x:Name="bottom"
Height="5"
VerticalAlignment="Bottom"
Margin="5,0,5,0" />
<Rectangle
Stroke="{x:Null}"
Fill="#24282A"
HorizontalAlignment="Left"
Margin="0,5,0,5"
Width="5"
x:Name="left"/>
<Rectangle
Stroke="{x:Null}"
Fill="#24282A"
Margin="0,5,0,5"
Width="5"
HorizontalAlignment="Right"
x:Name="right" />
<Rectangle
Stroke="{x:Null}"
Fill="#24282A"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"
Width="5"
Height="5"
x:Name="bottomLeft" />
<Rectangle
Stroke="{x:Null}"
Fill="#24282A"
VerticalAlignment="Bottom"
Height="5"
Width="5"
HorizontalAlignment="Right"
x:Name="bottomRight" />
<Rectangle
Stroke="{x:Null}"
Fill="#24282A"
HorizontalAlignment="Right"
Width="5"
Height="5"
VerticalAlignment="Top"
x:Name="topRight" />
<Rectangle
Stroke="{x:Null}"
Fill="#24282A"
HorizontalAlignment="Left"
Width="6"
VerticalAlignment="Top"
Height="5"
x:Name="topLeft" />
</Grid>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
As you can see, there is a label called "WindowName". i want this label to be kind of Title bar in my custom window, and i wanna call it's property content from my main wpf application which inherits from this custom window. Everything works ok, except i have no idea how i should call this label to set it's content. Any help would be appreciated
You would want to bind the content of that Label to the Title property of the base Window class since the base class already has a dependency property that you can just reuse. All you will need to do is update the xaml for you label component as below:
<Label x:Name="WindowName" Content={TemplateBinding Title} Background="#24282A" Foreground="White" Grid.Row="0" Grid.Column="0"/>
You could also override OnApplyTemplate in your CustomWindow and use a method like FindName to get the Label using its name and then updating it through a direct reference, but the binding way is much cleaner so I wouldn't consider that route although I wanted to at least mention it.

How to appose WrapPanel items of different heights (vertically)?

This is how it looks like right now:
and this is how I'd like to have it:
As shown the tiles should be apposed as densely as possible with only a set margin between them.
And here's my code:
<Grid Background="Gray">
<TextBox x:Name="BoardNameTextBox" HorizontalAlignment="Left" Height="23" Margin="40,3,0,0" TextWrapping="Wrap" Text="pol" VerticalAlignment="Top" Width="120"/>
<Button Content="Button" HorizontalAlignment="Left" Margin="491,3,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
<Grid Margin="0,30,0,0" Background="WhiteSmoke">
<WrapPanel VerticalAlignment="Top" HorizontalAlignment="Left">
<WrapPanel.Resources>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Width" Value="80" />
<Setter Property="Height" Value="80" />
<Setter Property="Margin" Value="3" />
<Setter Property="Fill" Value="#4DB4DD" />
</Style>
</WrapPanel.Resources>
<Rectangle Width="150" />
<Rectangle />
<Rectangle />
<Rectangle />
<Rectangle Width="200"/>
<Rectangle Height="25"/>
<Rectangle Height="40"/>
<Rectangle />
<Rectangle Width="220"/>
<Rectangle Height="30"/>
<Rectangle Height="30"/>
<Rectangle Width="150" />
<Rectangle />
</WrapPanel>
</Grid>
</Grid>
The code is of course a sample code for my particular problem - later on it should just be a wrap panel (or any other control) with the items (which are custom controls) added programmatically (like "WrapPanel1.Children.Add(r);"). I hope the images are self-explanatory.
What you are looking for is called cascading layout.it has a very popular implementation in javascript called Masonry which has a WPF counterpart known as WPF-Masonry .check preceding links for detail and demo.

How can I use multiple ControlTemplates in a XAML-file?

I'm having this annoying problem with WPF that I can't get my head around.
What I'm trying to create, is a very basic implementation of a drawing program (it's a school assignment) with movable tool windows, like in Photoshop.
I've managed to figure out that I can use this element "Thumb" to implement simple Drag functionality. Since the Thumb element itself is not visible, and the object that I'm using as a container (a DockPanel) does not have a DragDelta property, I simply created a ControlTemplate and attached it to the Thumb, so now I have a draggable color picker that works okay. So far so good.
But, problems arise when I want to create additional ControlTemplates, to use for other Thumb-elements that I plan to use (I get the error: The property 'VisualTree' is set more than once.).
This is what I want help with. I have pasted my whole Window.Resources-tag here so you can see what's going on.
<Window.Resources>
<Style x:Key="toolBoxBtn" TargetType="Button">
<Setter Property="Width" Value="60" />
<Setter Property="Height" Value="60" />
<Setter Property="Margin" Value="5" />
<Setter Property="DockPanel.Dock" Value="Top" />
</Style>
<Style x:Key="style1" TargetType="{x:Type Thumb}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<DockPanel Background="#e6e6e6" HorizontalAlignment="Left" Margin="0" Height="auto" Width="auto" Canvas.Left="640" Canvas.Top="8">
<Label VerticalAlignment="Top" DockPanel.Dock="Top" Background="#282828" Foreground="white" Content="Colors" HorizontalAlignment="Stretch" Width="auto" Height="auto" />
<StackPanel>
<StackPanel Orientation="Horizontal" Margin="7" VerticalAlignment="Center">
<Rectangle DockPanel.Dock="top" Name="red" Fill="Red" Height="20" Width="20" Stroke="Black" MouseDown="getColor" />
<Rectangle DockPanel.Dock="top" Name="blue" Fill="Blue" Height="20" Width="20" Stroke="Black" MouseDown="getColor"/>
<Rectangle DockPanel.Dock="top" Name="green" Fill="GreenYellow" Height="20" Width="20" Stroke="Black" MouseDown="getColor"/>
<Rectangle DockPanel.Dock="top" Name="customColorSlot1" Fill="White" Height="20" Width="20" Stroke="Black" MouseDown="getColor" />
<Rectangle DockPanel.Dock="top" Name="customColorSlot2" Fill="White" Height="20" Width="20" Stroke="Black" MouseDown="getColor"/>
<Rectangle DockPanel.Dock="top" Name="customColorSlot3" Fill="White" Height="20" Width="20" Stroke="Black" MouseDown="getColor"/>
</StackPanel>
<GroupBox Header="Selected Color">
<Rectangle Name="currentColor" Fill="White" Height="40" Width="40" Stroke="Black" MouseDown="test"/>
</GroupBox>
</StackPanel>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="fillTool" TargetType="{x:Type Thumb}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Ellipse HorizontalAlignment="Left" Height="19" Margin="310,330,0,0" VerticalAlignment="Top" Width="19" Fill="Blue"/>
<Ellipse HorizontalAlignment="Left" Height="12" Margin="317,316,0,0" VerticalAlignment="Top" Width="12" Fill="Blue"/>
<Ellipse HorizontalAlignment="Left" Height="8" Margin="307,320,0,0" VerticalAlignment="Top" Width="7" Fill="Blue"/>
<Ellipse HorizontalAlignment="Left" Height="3" Margin="317,302,0,0" VerticalAlignment="Top" Width="3" Fill="Blue"/>
<Ellipse HorizontalAlignment="Left" Height="5" Margin="311,310,0,0" VerticalAlignment="Top" Width="5" Fill="Blue"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
What could be the problem here?
ControlTemplate can only contain one child. Try and change it to a Canvas instead
<Style x:Key="fillTool" TargetType="{x:Type Thumb}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Canvas>
<Ellipse HorizontalAlignment="Left" Height="19" Margin="310,330,0,0" VerticalAlignment="Top" Width="19" Fill="Blue"/>
<Ellipse HorizontalAlignment="Left" Height="12" Margin="317,316,0,0" VerticalAlignment="Top" Width="12" Fill="Blue"/>
<Ellipse HorizontalAlignment="Left" Height="8" Margin="307,320,0,0" VerticalAlignment="Top" Width="7" Fill="Blue"/>
<Ellipse HorizontalAlignment="Left" Height="3" Margin="317,302,0,0" VerticalAlignment="Top" Width="3" Fill="Blue"/>
<Ellipse HorizontalAlignment="Left" Height="5" Margin="311,310,0,0" VerticalAlignment="Top" Width="5" Fill="Blue"/>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Categories