WPF - Button on Image Moves at Run Time - wpf

I have a program that displays a grid that contains an image and 3 buttons. The buttons have been sized in the Visual Studio designer to fit inside separate circles (each approx 1/4" in diameter). When I run the program each of the buttons all move down and to the right about 1/2 the width of the button. If I add an explicit width and height to each button I can keep the size the same but the buttons still moves slightly to the right and maybe even down slightly.
My guess is that it has to do with how Windows has displayed the image to fit on the screen and that this scaling/positioning has not been applied to the buttons. If so, I have no idea how to correct the issue.
Any ideas on how to correct this problem would be greatly appreciated.
Chris
My XAML code:
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="{Binding Source={x:Static SystemParameters.WorkArea}, Path=Height}"
Width="{Binding Source={x:Static SystemParameters.WorkArea}, Path=Width}"
WindowStartupLocation="CenterScreen"
Background="CornflowerBlue"
ResizeMode="CanMinimize"
>
<Window.Resources>
<Style x:Key="{x:Type Button}" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Black"/>
<Setter Property="Opacity" Value="1"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid Name="grid1">
<Image Name="image" Source="D:\CEP\Image1.jpg" Stretch="Uniform">
</Image>
<Button Margin="494,0,1155,801" Click="button_407_Click"></Button>
<Button Margin="339,107,1310,856" />
<Button Margin="401,102,1248,860" />
</Grid>

Set the Stretch property of the Image to None to prevent the image from sizing.
You have positioned the buttons by setting their margins. As soon as the window is resized their positions and sizes will change.
Add a Canvas to the grid and put the image and the buttons on the canvas using absolute positioning (Canvas.Left="..." Canvas.Top="..."
If, after doing this, you do not like the results because you still want to resize the the images and move the buttons in sync you could wrap the Canvas in a ViewBox to make it scale.
EDIT
<Grid>
<Viewbox>
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Image Source="Images\wp_1680.jpg" Width="300" Height="200"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Canvas Width="300" Height="200"
HorizontalAlignment="Center" VerticalAlignment="Center">
<Button Canvas.Top="25" Canvas.Left="50" Content="OK"/>
<Button Canvas.Top="125" Canvas.Left="150" Content="Cancel"/>
</Canvas>
</Grid>
</Viewbox>
</Grid>
This solution includes nice scaling through the Viewbox, but it can be removed as well.
Please organize all your posts. If you want to say something about my answer add it as a comment to my answer if you want add to your question, edit the question.

Related

Make form semi transparent to see form's background image

I'm using WPF (c#) form with background image (background imagebrush).
I want to make all the UI elements(button , title, textbox)... become semi-transparent so that they don't cover the image completely,
but the background image still being visible (not semi-transparent)
I would like a way we can do it without having to set all the opaque value of UI elements.
Maybe this could help
<Window.Resources>
<Style x:Key="transparentControls" TargetType="Button">
<Setter Property="Opacity" Value="0.1"/>
<Setter Property="Background" Value="Green"/>
</Style>
</Window.Resources>
<Grid>
<Grid.Background>
<ImageBrush ImageSource="MyImage.jpg"/>
</Grid.Background>
<Button Height="24" Width="100" Style="{StaticResource transparentControls}" VerticalAlignment="Top" Content="Hey"/>
<Button Height="24" Width="100" Style="{StaticResource transparentControls}" Content="There"/>
<Button Height="24" Width="100" Style="{StaticResource transparentControls}" VerticalAlignment="Bottom" Content="Click Me"/>
</Grid>
Just try to put all your UI elements in a Canvas or Grid and set the Opacity of that parent element.
Like that:
<Canvas Opacity="1">
<Button Width="100" Height="100"></Button>
</Canvas>
I hope this was what you meant.

Blur effect on image as a window background

I have a window in my WPF app with an image as a background. I want that image to be blurred. This is how I do it:
This is my window:
<Window x:Class="kiosk.UI.Views.PageSwitch"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="clr-namespace:myProjectName.Converters"
Title="PageSwitch" Height="1024" Width="1280"
Style="{StaticResource WindowStyle}"
WindowStyle="None" ResizeMode="NoResize"
WindowStartupLocation="CenterScreen">
</Window>
And here's the style I apply to it:
<Style x:Key="WindowStyle" TargetType="{x:Type Window}">
<Setter Property="FontFamily" Value="Verdana" />
<Setter Property="Background">
<Setter.Value>
<VisualBrush>
<VisualBrush.Visual>
<Image Source="Images\myImage.png" >
<Image.Effect>
<BlurEffect Radius="20"/>
</Image.Effect>
</Image>
</VisualBrush.Visual>
</VisualBrush>
</Setter.Value>
</Setter>
</Style>
This works - the image is blurred. However, there's a thick black border of about 5 mm around the background image. Why is it there and how can I remove it?
Here's what I tried as an alternative:
<VisualBrush Viewbox="0, 0, 1280, 1024" ViewboxUnits="Absolute" >
and the border is removed but the image is stretched a lot. Almost half of the image isn't even shown.
How can I fix this?
Do it like shown in this answer to one of your previous questions. Put the Image control in a Grid with ClipToBounds set to true.
<VisualBrush>
<VisualBrush.Visual>
<Grid ClipToBounds="True">
<Image Source="Images\myImage.png">
<Image.Effect>
<BlurEffect Radius="20"/>
</Image.Effect>
</Image>
</Grid>
</VisualBrush.Visual>
</VisualBrush>
I do a similar thing but just add the image as a element to the LayoutRoot. From this I set the margin to minus out the blur radius to avoid blurring in edges. If you're black border fades in I would suspect this is the issue.
<Image Source="pack://siteoforigin:,,,/image.jpg" Stretch="UniformToFill" Margin="-50">
<Image.Effect>
<BlurEffect Radius="100"/>
</Image.Effect>
</Image>

WPF: Textblock Font size should be even when its size change

I create a custom button in my application as following
<Button x:Class="MyApp.ButtonMainMenuSubCat"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="100" d:DesignWidth="536">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Grid Name="gridParent">
<Image Name="imgTransparent" Source="/MyApp;component/Resources/LeftCategoryTransparent.png" Stretch="Fill" Margin="0,0,0,0" />
<Image Name="Part_Pressed" Source="/MyApp;component/Resources/PressedMainScreenSubMenu.png" Stretch="Fill" Margin="0,0,0,4" Visibility="Hidden"/>
<Image Name="Focused" Source="/MyApp;component/Resources/MainSubMenuFocus.png" Margin="-3,0,-3,3" Stretch="Fill" Visibility="Hidden" />
<Image Name="Seperator" Source="/MyApp;component/Resources/MainSubMenuSeperator.png" Margin="5,0,5,-1" Stretch="Uniform" VerticalAlignment="Bottom"/>
<TextBlock Name="lblTitle" Text="{TemplateBinding Content}" HorizontalAlignment="Left" Foreground="Gray" FontWeight="{TemplateBinding FontWeight}" FontSize="24" Margin="10" VerticalAlignment="Center" TextWrapping="WrapWithOverflow" TextAlignment="Left"/>
</Grid>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<!--<Setter TargetName="Pressed" Property="Visibility" Value="Visible"/>-->
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter TargetName="Focused" Property="Visibility" Value="Visible"/>
<Setter TargetName="lblTitle" Property="Foreground" Value="#f8cb1c" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
In my application, I call web service and depending upon the no of items, i create button for each item and finally add these button in StackPanel. Its works well. Stakpanel layout is on left side in screenshot. Now problem is that when I run this application on different machine which have different Screen resolution (like 1920 *1200), then font size seems too small. So i want to adjust font size when container size change. One option is use ViewBox but in case of ViewBox all buttons seems like have different font size and TextWrapping is not possible.
So my actual requirement is that increase/decrease the textblock's font size with TextWrapping and font size must be even for all buttons.
You can use a LayoutTransform based on the screen resolution, you can either scale up your stackpanel or scale up the whole window depending on the resolution.
For the stackpanel:
<StackPanel>
<StackPanel.LayoutTransform>
<ScaleTransform x:Name="ScaleTransform" />
</StackPanel.LayoutTransform>
<Button>A</Button>
<Button>B</Button>
<Button>C</Button>
<Button>D</Button>
</StackPanel>
Then bind the ScaleX and ScaleY to a formula based on the resolution. An example of this:
double scale = System.Windows.SystemParameters.PrimaryScreenHeight / 720;
//using 720p as the base screen height.
this.ScaleTransform.ScaleX = scale;
this.ScaleTransform.ScaleY = scale;
You may want to do this in a ViewModel with some databinding if you are using MVVM.

Why does the style change when I add an an accelerator to my button?

When I have my button's content as a normal string e.g. <Button Content="Ok" /> then button behaves as normal. But if I change the content to have a keyboard accelerator e.g. <Button Content="_Ok" /> the button's style changes to have different margins and sizes.
I have a TextBlock style that doesn't have a key so is being applied to all TextBlocks, my question is why is it applied when it the content has an accelerator and not when it doesn't?
Edit: For extra info: The default style is inside the resources of a StackPanel that is the button is inside. I guess the question is really, why doesn't the default TextBlock style get applied when the button has an accelerator?
WPF adds a TextBlock to each Button (and Menu) with an accelerator.
You can see this effect by running the following XAML (remember to hook up the Command if needed).
The key to fixing the problem, given the scope of your question, is to set the TextAlignment to a value of Center for the TextBlock. If you set the Width for the TextBlock style (my line is commented out below) the text will start to shift. Adding HorizontalAlignment = Center also helps center text in the TextBlock/Button, but this also impacts the other TextBlock controls.
<Window x:Class="ButtonAccelerator.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Main Window" Height="400" Width="800">
<Window.Resources>
<Style TargetType="TextBlock">
<!--<Setter Property="Width" Value="70"/>-->
<Setter Property="Height" Value="23"/>
<Setter Property="Background" Value="Pink"/>
<Setter Property="TextAlignment" Value="Center"/>
</Style>
<Style TargetType="Button">
<Setter Property="Width" Value="70"/>
<Setter Property="Height" Value="23"/>
</Style>
</Window.Resources>
<DockPanel>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel
Grid.Row="1" Grid.Column="1"
HorizontalAlignment="Right"
Orientation="Horizontal">
<TextBlock Text="OK" />
<Button
Content="OK"/>
<Button
Content="_OK"/>
</StackPanel>
</Grid>
</DockPanel>
</Window>
You should verify this with Snoop but <Button Content="Ok" /> produces a TextBlock to handle the text within a button. Since TextBlock doesn't support accelerator keys I would bet that <Button Content="_Ok" /> causes it to produce a Label instead since a Label will take care of the accelerator key.

WPF Image Zooming

I have a Viewbox with an Image inside of it. This is great since the Viewbox will scale the Image to fit the window. However, I need to be able to zoom the image to its full size and show scroll bars and I am having a hard time figuring out how to do this.
Here's what I have right now. Can anyone give some pointers on how I can modify this to implement the above functionality?
<Viewbox x:Name="viewbox">
<StackPanel>
<Image x:Name="image" Source="ranch.jpg" />
</StackPanel>
</Viewbox>
Edit:
Just to clarify. I need both ways of viewing the image, the viewbox style of fitting the window AND the ability to toggle to an Actual Size view that shows scrollbars and doesn't resize the image.
You don't need a Viewbox here, by putting the Image in a ScrollViewer and manipulating the VerticalScrollBarVisibility and HorizontalScrollBarVisibility properties, you can make the Image scale or not:
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<CheckBox x:Name="chkActualSize" Grid.Row="0" Content="Actual Size"/>
<ScrollViewer Grid.Row="1">
<ScrollViewer.Style>
<Style TargetType="{x:Type ScrollViewer}">
<Setter Property="HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="VerticalScrollBarVisibility" Value="Disabled"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=chkActualSize}" Value="True">
<Setter Property="HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ScrollViewer.Style>
<Image Source="http://sipi.usc.edu/database/misc/4.1.01.tiff" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</ScrollViewer>
</Grid>
<ScrollViewer HorizontalScrollBarVisibility="Auto">
<Viewbox>
<Image Source="ranch.jpg"/>
</Viewbox>
</ScrollViewer>
Based on your edit that you need to toggle the two approaches, I would do this in one of two ways.
Have two elements with the image. The Image element inside a ScrollViewer without the Viewbox will give you the full size image, and the Viewbox version will scale it. Then you can toggle the two depending on what you want to show.
Use a binding expression on the Height and Width properties of the Image and enclose it inside the scrollviewer. When you want to scale it (in some sort of trigger), set the Height to a binding expression that accesses the ActualHeight property of the ScrollViewer or whatever container is just above that (using RelativeSource to access the nearest ancestor something like the following):
{Binding Path=ActualHeight,
RelativeSource={RelativeSource AncestorType={x:Type ScrollViewer}}}
Thought I would post my solution for anyone looking.
<Slider Width="200" Value="500" Interval="25" Maximum="1000" x:Name="TestImageSlider" Minimum="-50" />
<ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Auto">
<Image Source="{Binding SelectedScannedImage.ScannedImage}" Width="{Binding Path=Value, ElementName=TestImageSlider}" />
</ScrollViewer>

Resources