WPF databinding problem - c#

I have a grid inside a canvas on a tab.
The grid contains a large bitmap image,
I have(tried to) bound the size of the grid to the size of the tab and also have a five pixel margin around the grid.
imageTab.cs
public ImageTab(SendInfo sendInfo, int numImge, int numAccs)
{
imageDisplay = new ImageDisplay(sendInfo, numImge, numAccs);
imageDisplay.ClipToBounds = true;
CreateCanvas();
}
private void CreateCanvas()
{
Canvas canvas = new Canvas();
canvas.Children.Add(imageDisplay);
this.AddChild(canvas);
}
ImageDisplay.xaml
<UserControl x:Class="MyProj.ImageDisplay">
<Grid Margin="5,5,5,5" Height="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=TabControl, AncestorLevel=1}, Path=ActualHeight}">
<Image/>
</Grid>
</UserControl>
The grid comes off the bottom of the tab area slightly causing the bottom of the image to be cut off.
Is there a problem with my databinding, do I need to apply some sort of offset to it? (size of tab - 10pixels for the margin?)

You don't need to set the Height property at all (also realize that it is incorrect to do so as you have it when you consider the 5 pixel margin, i.e., it would be off by 10 pixels).
Just leave VerticalAlignment and HorizontalAlignment at their default values (which is Stretch) to get the effect you are after here.
Try this on a new Window to see what I mean:
<Window x:Class="WpfApplication9.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="438" Width="587" Background="Pink">
<Grid Background="Black" Margin="5">
</Grid>
</Window>
The grid here will be black and will always stretch to the size of the window, using a 5 pixel margin which you will see because the Window's back color is pink.

Related

Changing size of the frame and elements in UWP

I want to know if there is a way to resize the frame and the elements inside of it when the window size change. I always want to have the same proportion in the size of the elements inside the frame.
Example:
1- Windowsize = 100(in x) and Imagesize = 50(in x) locationx = 25
2- Windowsize = 50(in x) and Imagesize = 25(in x) location x = 12.5(~12)
In this case, the windowsize is "something", imagesize is 1/2 of "something" and locationx of the image is 1/4 of something. I wan't to do something like this but with every element inside the frame.
Thanks!
You can use the <ViewBox/> control which does exactly that.
<Page>...
<Grid>
<ViewBox HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<StackPanel>
<Button Content="test" HorizontalAlignment="Left"/>
<TextBlock Text="some text"/>
</StackPanel>
</ViewBox>
</Grid>
</Page>
In the example below, the ViewBox is placed inside a Grid and stretched both Horizontally and Vertically which causes it to stretch with the Page resize.
Reference docs here.

Anchoring a label

I am relatively new to WPF and trying to insert a label computed by an algorithm inside a panel. I create the label in my code. I do not use the designer for the label.
The problem is that when I add the label to the panel, it gets resized when I resize the Window. I want the label to be a fixed height and width. Apparently it is anchored to the bottom of the window (I know that from the usual Winforms behavior).
How can I unanchor it, or give it a fixed size?
EDIT
XAML:
<Window x:Class="TestWrapper.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MyTest" Height="483.833" Width="525" Loaded="Window_Loaded">
<Grid x:Name="MyGrid" Margin="0">
<Grid.Background>
<ImageBrush ImageSource="Resources/Background.jpg" Stretch="Uniform"/>
</Grid.Background>
</Grid>
</Window>
Code:
if (!_initialized)
{
Label lbl = new Label()
{
Content = "Test",
FontSize = 36,
Foreground = new SolidColorBrush(Colors.Red),
Background = new SolidColorBrush(Colors.Black),
HorizontalContentAlignment = System.Windows.HorizontalAlignment.Center,
VerticalAlignment = System.Windows.VerticalAlignment.Top
};
this.MyGrid.Children.Add(lbl);
lbl.Margin = new Thickness(0, this.MyGrid.ActualHeight + lbl.ActualHeight, 0, 0);
this._initialized = true;
}
If you simply want to hardcode a width and height, explicitly set the Width and Height attributes of your label:
<Label Width="100" Height="20">Hello World</Label>
A Grid will automatically centre and stretch its children, given no other information, and this is the default behaviour you're likely seeing.
(If you provide more code/markup, I can give a more detailed explanation.)
I suggest to use instead the HorizontalAlignment and VerticalAlignment.
<Label HorizontalAlignment="Center" VerticalAlignment="Center" Content="Hello World" />
In this way, the label is automatically centered and the size is dynamically adapted by the WPF Engine.
Remember also that a WPF interface should not be developed by code behind, in most of cases, if not always. You can easily use the Xaml to resolve your problem.

Horizontal image scaling with ScaleTransform in WPF

I have an image in a WPF window with the default Stretch setting, Uniform, and am making an attempt to make it fill the screen horizontally. I do not wish to use a different Stretch setting as this is supposed to a learning experience. The image dimensions being loaded are 420x800. This is the XAML for the window..
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Red" Height="1200" Width="840">
<Image Name="Image" Source="{Binding SourceUri}">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform x:Name="Scale" />
<TranslateTransform x:Name="Translate" />
</TransformGroup>
</Image.RenderTransform>
</Image>
</Window>
On the code-behind, I am attempting to calculate the scaling to zoom the image to fill the horizontal screen and I am using translate transform the move it to the center of the screen. The following bit of code is obviously wrong...
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace WpfApplication1 {
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
DataContext = this;
double ImageWidth = 420;
Scale.ScaleX = Width / ImageWidth;
Translate.X = -(ImageWidth / 2);
}
public string SourceUri {
get {
return #"C:\Users\Roel\Desktop\test.png";
}
}
}
}
I am attempting to understand how stretching and transformations are working together but I am having difficulty with this. I would appreciate all insights, even references to detailed explanations, as I have trouble finding any informational source explaining clearly and concisely how the transformations are applied.
You would usually just do this:
<Image Name="Image" Source="{Binding SourceUri}" Stretch="Fill"/>
In case you really need to calculate the stretch transformation manually, you would only need a ScaleTransform, no TranslateTransform, and you would put that into the LayoutTransform of the Image control. Moreover, the Image control would have to be placed into a Grid, which provides the size of the Windows's "client area". You can't calculate anything based on the Window's Width (or ActualWidth) as that includes the width of the Window's borders.
<Grid SizeChanged="Grid_SizeChanged">
<Image Name="image" Source="{Binding SourceUri}">
<Image.LayoutTransform>
<ScaleTransform x:Name="scale"/>
</Image.LayoutTransform>
</Image>
</Grid>
In the Grid's SizeChanged handler you would calculate the scaling as shown below.
private void Grid_SizeChanged(object sender, SizeChangedEventArgs e)
{
scale.ScaleX = e.NewSize.Width / image.Source.Width;
scale.ScaleY = e.NewSize.Height / image.Source.Height;
}

Find size of a Canvas

How to find out size of an Canvas that created in xaml file?
for example I create an Canvas by
<Page
x:Class="MyApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Canvas x:Name="canvas" Background="White">
</Canvas>
</Page>
and full screen is white or whatever color I specified for that canvas
than in my class I tried but with no luck
double h = canvas.Height; // NaN
h = canvas.ActualHeight; // 0
so how do I found out the actual size of that canvas? or the size is 0 but than how to make the canvas full screen size?
I am new C# and metro developer and so confused how everything works compare to iOS.
Where in your code are you checking the size of the Canvas? I'm assuming you're doing it in the page constructor or somewhere else that is running before the UI layout has run. In this case, all auto sized elements (NaN height or width) still have their default size. If you check the size after layout has completed, like in a Loaded event handler in your page, then you should see the true rendered size.
If your Canvas happens to only contain one Image, you can use:
var Width = ((Image) (MyCanvas.Children[0])).Width;
var Height = ((Image) (MyCanvas.Children[0])).Height;
Of course, you can switch out the two Image casts for another element, if your Canvas contains one of some other item.
Alternatively just give the wrapped Image (or other element) a name, and reference it as MyImage.Width.

WPF element positioning on a Canvas

I have a point on a canvas that I want to place an ellipse. I want the centre of the ellipse to be over this point. At the moment the top left most edge of the ellipse is over this point.
I know I can shift the ellipse programmatically on the canvas but I was wondering if there is a way to tell WPF to centre the element over the point instead of sizing it from the top left???
I do not know of any in built in feature in Ellipse to set its center on a point, but you can extend the Ellipse class to do it.
Add this class to project
public static class EllipseX
{
public static void SetCenter(this Ellipse ellipse, double X, double Y)
{
Canvas.SetTop(ellipse, Y - ellipse.Height/2);
Canvas.SetLeft(ellipse, X - ellipse.Width/2);
}
}
Then in xaml create the Ellipse
<Window x:Class="WpfApplication2.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">
<Canvas Background="LightGray">
<Ellipse
Name="myEllipse"
Fill="Red"
Height="75"
Width="75"
/>
</Canvas>
</Window>
Then write int following code in code behind:
myEllipse.SetCenter(200,200);
The advantage of this is that you do not have to repeat the logic of finding center in every ellipse you create.
Hope this helps.
No there is no such way. Top Left is a top left, because it's a top left :). Alternatively instead of shifting ellipse you can shift point, if you know ellipse dimensions.
You could apply a TranslateTransform to the Ellipse, but that requires you to know its width and height.
I had a similar problem setting the Center of a ScaleTransform in a style of different sized controls.
Ended up using a converter to bind to the ActualWidth/ActualHeight divided by 2. THe same should work for you with a TranslateTransform as Rune Grimstad mentioned.
<ScaleTransform CenterX="{Binding ActualWidth, Converter={StaticResource divisionConverter}}"
CenterY="{Binding ActualHeight, Converter={StaticResource divisionConverter}}"
ScaleX="1.2"
ScaleY="1.2" />

Categories

Resources