Why does the button keep going out of bounds? (WPF Application) - c#

I'm quite new to C# so expect faulty/lengthy code for no good reason.
So i was playing around with WPF Applications as i wanted to know how to make a button move when hovered over it- Which i managed to do but now it goes out of bounds?
XAML code:
<Window x:Class="Opdracht7.MainWindow"
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:local="clr-namespace:Opdracht7"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Button x:Name="klikmij" Content="Click me!" MouseEnter="onMouseEnter" Click="onMouseClick" HorizontalAlignment="Center" VerticalAlignment="Center" RenderTransformOrigin="-0.989,-0.519" Height="33" Width="68"/>
</Grid>
</Window>
C# code dump:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using static System.Net.Mime.MediaTypeNames;
namespace Opdracht7
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private void onMouseEnter(object sender, MouseEventArgs e)
{
Random rnd1 = new Random();
int value1 = rnd1.Next(0, 250);
int value2 = rnd1.Next(0, 250);
int value3 = rnd1.Next(0, 250);
int value4 = rnd1.Next(0, 250);
Debug.WriteLine(value1);
Debug.WriteLine(value2);
Debug.WriteLine(value3);
Debug.WriteLine(value4);
klikmij.Margin = new Thickness(value1,value2, value3, value4);
}
private void onMouseClick(object sender, RoutedEventArgs e)
{
MessageBox.Show("Congratulations! You won nothing!");
}
public MainWindow()
{
InitializeComponent();
}
}
}
I set random range from 0 to 250, because when i adjust it to the window's actual height 'n width it goes out of bounds even faster.
For some strange reason when it goes over 230-ish (could be lower) the button is gone until you enlargen the window size.
Did i overlook a vital piece 'o code?
EDIT:
https://gyazo.com/342b20fdbbcef2a4834ab95c37aaf30e <- gif of it happening
EDIT 2:
https://gyazo.com/f04e1d64f9880cd01aa53f9169954377 <- gif of resizing window

After playing a bit in the designer with different values, it looks like in Grid margins take precedence, and the button gets smaller to accomodate. In case when it disappears, it's calculated height just becomes 0.
Set width and height for the button manually, then change just the left and top margin, while setting rest to 0:
<Grid>
<Button Margin="250,250,0,0" Width="100" Height="100">TEST</Button>
</Grid>
Play with values in designer first to see what's happening when.
Better, do not use an element's Margin for layout. For absolute positioning, use a Canvas:
<Grid>
<Canvas>
<Button x:Name="klikmij" Content="Click me!"
MouseEnter="onMouseEnter" Click="onMouseClick"
Height="33" Width="68"/>
</Canvas>
</Grid>
with thic code behind:
private readonly Random rnd = new Random();
private void onMouseEnter(object sender, MouseEventArgs e)
{
Canvas.SetLeft(klikmij, rnd.Next(0, 250));
Canvas.SetTop(klikmij, rnd.Next(0, 250));
}

Related

C# WPF image load like progressbar

I'v a progressbar and an image.
When Progress Bar value is 50, image loaded by 50%.
I tried to add image as the progressbar foreground, but it have green shade. So ugly.
How can I do this?
To run this sample, you need a snake image which you can get from http://res.freestockphotos.biz/pictures/16/16242-illustration-of-a-green-snake-pv.png. I have used this url directly, but your should download image first and then use it.
You need a control template for your ProgressBar because you want to show percentage status too.
Otherwise normal ProgressBar would do.
Code can be used as is :
<Window x:Class="WpfControlTemplates._32794074.Win32794074"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Win32794074" Height="600" Width="1000">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="397*"/>
<RowDefinition Height="173*"/>
</Grid.RowDefinitions>
<ProgressBar x:Name="PBarCustom" Width="958" Height="200" Maximum="958" Value="958" Foreground="#FFE6E61F" Margin="17,185,17,11.932" ValueChanged="PBarCustom_ValueChanged">
<ProgressBar.Background>
<ImageBrush ImageSource="http://res.freestockphotos.biz/pictures/16/16242-illustration-of-a-green-snake-pv.png"/>
</ProgressBar.Background>
<ProgressBar.Template>
<ControlTemplate>
<Grid Background="{TemplateBinding Background}">
<Rectangle x:Name="Thumb" HorizontalAlignment="Left" Fill="#FFC5EA1F" Stroke="#FF0DB442" Width="{TemplateBinding Width}" />
<Ellipse Fill="#FF7DEEDE" Height="124" Stroke="#FF0DB442" Width="150" VerticalAlignment="Center" HorizontalAlignment="Center" Opacity="0.3"/>
<Label x:Name="tbStatus" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" FontWeight="Bold" FontSize="75" Foreground="#FF21BD76" Content="0" />
</Grid>
</ControlTemplate>
</ProgressBar.Template>
</ProgressBar>
<Button x:Name="BtnLoadSnake" Content="Load Snake" HorizontalAlignment="Left" Margin="462,14.068,0,0" VerticalAlignment="Top" Width="75" Click="BtnLoadSnake_Click" Grid.Row="1"/>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace WpfControlTemplates._32794074
{
/// <summary>
/// Interaction logic for Win32794074.xaml
/// </summary>
public partial class Win32794074 : Window
{
public Win32794074()
{
InitializeComponent();
}
DispatcherTimer timer;
private void BtnLoadSnake_Click(object sender, RoutedEventArgs e)
{
BtnLoadSnake.IsEnabled = false;
PBarCustom.Value = PBarCustom.Maximum;
Rectangle thumb = (Rectangle)PBarCustom.Template.FindName("Thumb", PBarCustom);
thumb.Width = PBarCustom.Value;
Label status = (Label)PBarCustom.Template.FindName("tbStatus", PBarCustom);
status.Content = ((int)(100 - ((100 * PBarCustom.Value) / PBarCustom.Maximum))).ToString();
Dispatcher disp = PBarCustom.Dispatcher;
EventHandler pBarCallbackHandler = new EventHandler(pBarCallback);
timer = new DispatcherTimer(TimeSpan.FromSeconds(0.5), DispatcherPriority.Normal, pBarCallback, disp);
}
private void pBarCallback(object sender, EventArgs e)
{
PBarCustom.Value -= 13;
Rectangle thumb = (Rectangle)PBarCustom.Template.FindName("Thumb", PBarCustom);
thumb.Width = PBarCustom.Value;
Label status = (Label)PBarCustom.Template.FindName("tbStatus", PBarCustom);
status.Content = ((int)(100 - ((100 * PBarCustom.Value) / PBarCustom.Maximum))).ToString();
if (PBarCustom.Value == 0)
timer.Stop();
}
private void PBarCustom_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if(e.NewValue == 0)
BtnLoadSnake.IsEnabled = true;
}
}
}
i had similar scenario.
if you want the scroll bar to be just a rectangle,
easiest way to make it:
1- add an image to your window.
2- put a grid on it in such a way that the grid hides the image.
3- programatically change the width or height of the grid.
tell me if you needed an example code.

DispatcherTimer does not fire

I just got started in Windows Store App development and I just wanted a very simple application: Pretty much a progres bar that fills up from left to right, but even this task is apparently not achievalbe for me.
I have the following code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace TimeLoader
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
private DispatcherTimer refreshTimer;
public MainPage()
{
this.InitializeComponent();
}
void refreshTimer_Tick(object sender, object e)
{
TimePassedBar.Value += 5;
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
TimePassedBar.Value = 50;
new DispatcherTimer();
this.refreshTimer = new DispatcherTimer();
this.refreshTimer.Interval = new TimeSpan(0, 0, 0, 100);
this.refreshTimer.Tick += refreshTimer_Tick;
this.refreshTimer.Start();
}
}
}
<Page
x:Class="TimeLoader.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TimeLoader"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" Loaded="Page_Loaded">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<ProgressBar Grid.Row="0" Grid.Column="0" Height="150" Value="75" VerticalAlignment="Center" Name="TimePassedBar"/>
</Grid>
</Page>
Now the same Setup works pretty fine when I do it in WPF but the Tick Event never fires when I start this code built as a Windows store app. Is there something Special I have to pay Attention to when building Windows Store Apps? I have looked high and low and sadly have found nothing on this matter.
Your code was working fine. You just didn't wait long enough to notice. :)
private void Page_Loaded(object sender, RoutedEventArgs e)
{
TimePassedBar.Value = 50;
this.refreshTimer = new DispatcherTimer();
this.refreshTimer.Interval = TimeSpan.FromMilliseconds(100);
this.refreshTimer.Tick += refreshTimer_Tick;
this.refreshTimer.Start();
}
You are setting the TimeSpan as 100 seconds. You need to use the five-parameter overload to get milliseconds. But IMHO it's easier and more readable to just use the FromMilliseconds() method (as above).
Also, you don't need to create a DispatcherTimer object twice, especially when you're going to ignore the first one completely. :)

WPF image inside border is not fully drawn

I have an image within a border:
XAML:
<Window x:Class="TestProgram.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Test" Height="350" Width="525">
<DockPanel>
<Grid DockPanel.Dock="Top">
<!---->
</Grid>
<ListBox DockPanel.Dock="Left"/>
<Grid DockPanel.Dock="Top">
<!---->
</Grid>
<Border x:Name="testBorder" ClipToBounds="True" Background="Gray">
<Image x:Name="testImage" Source="test.png" Opacity="1" Stretch="None"
MouseLeftButtonDown="testImage_MouseLeftButtonDown"
MouseLeftButtonUp="testImage_MouseLeftButtonUp"
MouseMove="testImage_MouseMove"
/>
</Border>
</DockPanel>
</Window>
C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace TestProgram
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private Point start;
private Point origin;
public MainWindow()
{
InitializeComponent();
TransformGroup group = new TransformGroup();
TranslateTransform tt = new TranslateTransform();
group.Children.Add(tt);
testImage.RenderTransform = group;
}
private void testImage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
testImage.CaptureMouse();
TranslateTransform tt = (TranslateTransform)((TransformGroup)testImage.RenderTransform).Children.First(tr => tr is TranslateTransform);
start = e.GetPosition(testBorder);
origin = new Point(tt.X, tt.Y);
}
private void testImage_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
testImage.ReleaseMouseCapture();
}
private void testImage_MouseMove(object sender, MouseEventArgs e)
{
if (testImage.IsMouseCaptured)
{
TranslateTransform tt = (TranslateTransform)((TransformGroup)testImage.RenderTransform).Children.First(tr => tr is TranslateTransform);
Vector v = start - e.GetPosition(testBorder);
tt.X = origin.X - v.X;
tt.Y = origin.Y - v.Y;
}
}
}
}
I have added click & drag panning functionality, but the displayed size of the image is limited by the surrounding border, leaving only the top left corner of the image visible when the image is panned. This is the case even when i remove ClipToBounds="True"
ActualHeight and ActualWidth have values corresponding to the image's natural height and width, so why is the image clipped? What can I do to make the full image visible?
If you really want the border to overlay on top of the the image, then put them both in a <Grid> or <Canvas>
<Canvas>
<Image/>
<Borde/>
</Canvas>

Accessing a control - Missing a using directive or assembly reference

I am using WPF application in C# and I want at the beginning to draw a triangle.
This is the error that appears when I run the program:
'WpfApplication1.mainWindow' does not contain a definition for
'mainViewport' and no extension method for 'mainViewport' accepting a
first argument of type 'WpfApplication1.mainWindow' could be found.
(are you missing a using directive or an assembly reference?)
Here is my XAML page:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WPF 3D Chart" Height="455" Width="689">
<Grid>
<Viewport3D Name="mainViewport" ClipToBounds="True">
<Viewport3D.Camera>
<PerspectiveCamera
FarPlaneDistance="100"
LookDirection="-11,-10,-9"
UpDirection="0,1,0"
NearPlaneDistance="1"
Position="11,10,9"
FieldOfView="70" />
</Viewport3D.Camera>
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight
Color="White"
Direction="-2,-3,-1" />
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D>
</Grid>
</Window>
and this is my code: (the error appears on the last line of my code)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Media3D;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
System.Windows.Media.Media3D.Point3D point0 = new Point3D(-0.5, 0, 0);
System.Windows.Media.Media3D.Point3D point1 = new Point3D(0.5, 0.5, 0.3);
System.Windows.Media.Media3D.Point3D point2 = new Point3D(0, 0.5, 0);
System.Windows.Media.Media3D.MeshGeometry3D triangleMesh = new MeshGeometry3D();
triangleMesh.Positions.Add(point0);
triangleMesh.Positions.Add(point1);
triangleMesh.Positions.Add(point2);
int n0 = 0;
int n1 = 1;
int n2 = 2;
triangleMesh.TriangleIndices.Add(n0);
triangleMesh.TriangleIndices.Add(n1);
triangleMesh.TriangleIndices.Add(n2);
System.Windows.Media.Media3D.Vector3D norm = new Vector3D(0, 0, 1);
triangleMesh.Normals.Add(norm);
triangleMesh.Normals.Add(norm);
triangleMesh.Normals.Add(norm);
System.Windows.Media.Media3D.Material frontMaterial = new DiffuseMaterial(new SolidColorBrush(Colors.Blue));
System.Windows.Media.Media3D.GeometryModel3D triangleModel = new GeometryModel3D(triangleMesh, frontMaterial);
triangleModel.Transform = new Transform3DGroup();
System.Windows.Media.Media3D.ModelVisual3D visualModel = new ModelVisual3D();
visualModel.Content = triangleModel;
this.mainViewport.Children.Add(visualModel); //here appears the error
}
}
}
You are refering to the Viewport in the constructor. At that moment in time the Viewport has not been created yet.
Use the Loaded event handler of the Window like this
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
Loaded="Window_Loaded">
<Grid>
Do NOT leave the constructor empty! There is an important call in there! The InitializeComponent loads the UI of the Window.
As far as I can see you removed that call in your code and that causes the code to break as well. Use the Loaded handler, that is what is for.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
}
}
Your XAML creates a class named WPFChart.Window1 while your code modifies a class called WpfApplication1.MainWindow. I don't know which one is right, but you need to change one of them so they match.

After resolution change hidden animated window is transparent

I am animating a window's opacity
...
DoubleAnimation myDoubleAnimation =
new DoubleAnimation(1.0, 0.0, new Duration(TimeSpan.FromSeconds(0.25)), FillBehavior.Stop);
Storyboard.SetTargetName(myDoubleAnimation, "wndNumpad");
Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Window.OpacityProperty));
m_fadeOut = new Storyboard();
m_fadeOut.Children.Add(myDoubleAnimation);
m_fadeOut.Completed += new EventHandler(FadeOut_Completed);
...
private void FadeOut_Completed(object sender, EventArgs e)
{
// Only hide the running instance
this.Visibility = System.Windows.Visibility.Hidden;
// this.Close();
}
If the screen resolution of a monitor is changed after FadeOut_Completed() has run i.e. the window's opacity was animated and the window is hidden. Then reshowing the window will display the window almost transparent. At a guess I would say with the opacity it had when the window was hidden although the Window.Opacity property claims an opacity of 1. If I don't animate but simply set the opacity to 0 and hide the window and after the resolution change set the opacity back to 1 the window is reshown as expected. I have also tried setting the opacity back to 1 in the FadeOut_Completed.
Does anyone have an idea what is happening and how I can avoid the issue?
Regards
Markus
You must to have a transparent window (AllowsTransparency="True"), no-resizable (ResizeMode="NoResize") and with no border (WindowStyle="None"). In C# code, I created a DoubleAnimation that change the opacity of the window, and when it is complete, the window will be closed.
XAML code:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" Background="Red" WindowStyle="None" AllowsTransparency="True" ResizeMode="NoResize">
<Grid>
</Grid>
</Window>
C# code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DoubleAnimation da = new DoubleAnimation();
da.From = 1;
da.To = 0;
da.Duration = new Duration(TimeSpan.FromSeconds(2));
da.Completed += new EventHandler(da_Completed);
this.BeginAnimation(OpacityProperty, da);
}
void da_Completed(object sender, EventArgs e)
{
this.Close();
}
}
}

Categories

Resources