How to measure a canvas that has auto height and width - silverlight

I'm a beginner in silverlight so i hope i can get an answer that brings me some more light in the measure process of silverlight.
I found an interessting flap out control from silverlight slide control
and now I try to use it in my project. So that the slide out is working proper, I have to place the user control on a canvas. The user control then uses for itself the height of its content. I just wanna change that behavior so that the height is set to the available space from the parent canvas.
You see the uxBorder where the height is set. How can I measure the actual height and set it to the border?
I tried it with Height={Binding ElementName=notificationCanvas, Path=ActualHeight} but this dependency property has no callback, so the actualHeight is never set.
What I want to achieve is a usercontrol like the tweetboard per example on Jesse Liberty's blog
Sorry for my English writing, I hope you understand my question.
<Canvas x:Name="notificationCanvas" Background="Red">
<SlideEffectEx:SimpleSlideControl GripWidth="20" GripTitle="Task" GripHeight="100">
<Border x:Name="uxBorder"
BorderThickness="2"
CornerRadius="5"
BorderBrush="DarkGray"
Background="DarkGray"
Padding="5" Width="300"
Height="700"
>
<StackPanel>
<TextBlock Text="Tasks"></TextBlock>
<Button x:Name="btn1" Margin="5" Content="{Binding ElementName=MainBorder, Path=Height}"></Button>
<Button x:Name="btn2" Margin="5" Content="Second Button"></Button>
<Button x:Name="btn3" Margin="5" Content="Third Button"></Button>
<Button x:Name="btn1_Copy" Margin="5" Content="First Button"/>
<Button x:Name="btn1_Copy1" Margin="5" Content="First Button"/>
<Button x:Name="btn1_Copy2" Margin="5" Content="First Button"/>
<Button x:Name="btn1_Copy3" Margin="5" Content="First Button"/>
<Button x:Name="btn1_Copy4" Margin="5" Content="First Button"/>
<Button x:Name="btn1_Copy5" Margin="5" Content="First Button"/>
<Button x:Name="btn1_Copy6" Margin="5" Content="First Button"/>
</StackPanel>
</Border>
</SlideEffectEx:SimpleSlideControl>

Hey - a couple of things:
I'm guessing it's just a typo, but: "{Binding ElementName=MainBorder, Path=Height}" should be "{Binding ElementName=uxBorder, Path=Height}" (or ActualHeight)
The SlideEffect appears to set a clip geometry, which is going to affect how "big" it looks
RectangleGeometry clipRect = new RectangleGeometry();
clipRect.Rect = new Rect(0, 0, panel.ActualWidth, host.Height);
host.Clip = clipRect;
If you comment out the above lines from the slide control, you should see a noticeable change in how big the panel looks.

I think that the ActualWidth or ActualHeight properties are not settable only gettable.
For that you won't be able to use binding, maybe if you create the element after the page has been loaded, since the Canvas Actual Size on the moment of the creation will be unknown.
Why don't you try creating a Property for this, with two way binding, and sign the Canvas event on layoutUpdated and update the value of the property, therefore updating all dependent objects.
I Don't know if this event is the right one, by check if it help's you.

Related

WPF TextBox in DataTemplate of ToggleButton does not show text if in toolbar flyout

If I put the Column where the toolbar is hosted to be very big (800) then all the text is visible:
but if I put a smaller column this happens:
But I cannot understand why:
<DataTemplate x:Key="IconFilterButton">
<StackPanel Orientation="Horizontal">
<TextBlock
VerticalAlignment="Center"
Style="{StaticResource LargeIconStyle}"
Text="{Binding}" />
<TextBlock
Margin="6,0,0,0"
VerticalAlignment="Center"
DataContext="{Binding}"
Style="{StaticResource BodyTextStyle}"
Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ToggleButton}, Path=Tag}" />
</StackPanel>
</DataTemplate>
and here the definition
<ToggleButton
x:Name="DFilter"
Click="Filtering_Click"
Content=""
ContentTemplate="{StaticResource IconFilterButton}"
Tag="1d"
/>
<ToggleButton
x:Name="WFilter"
Click="Filtering_Click"
Content=""
ContentTemplate="{StaticResource IconFilterButton}"
Tag="1w"
/>
Even worst if I click on the button once they are out:
and then the text is visible but is wrong as the TextBlock is not considered in the object size:
The WPF ToolBar control uses a custom panel for the overflow Popup. In many styles, the ToolBarOverFlowPanel has a property WrapWidth set to a static value like 200. This determines how many items can be displayed before it wraps to another row in the popup.
I've created custom styling for this control and have found that the ToolBarOverFlowPanel used internally is buggy. That's probably the source of your problem.
You can re-template the ToolBar and wire-up a different value for WrapWidth to try to fix the issue, but my guess is that you'll still run into layout problems.
Otherwise, you might consider making your own replacement control.

How to control button layout in Xaml

Im having trouble controlling the exact layout of a button control with XAML.
It seems that whatever i do the button is of a minimum width.
I have a simple button with only a textblock inside the button. But the button has a lot of margin and padding that i cant seem to get rid of (i know of negative margins and padding).
The things i want to know is:
1. Why in the world was it designed this way.
2. what are the groundrules for controlling the exact layout of a button?
My code is as follows:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="80"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0"></StackPanel>
<Pivot Grid.Row="1">
<Pivot.Title>
<StackPanel Orientation="Horizontal" Margin="-15,-3,0,0" Background="red" Width="480">
<Button Background="Blue" x:Name="btnStudies" Click="btnMenuItem_Click" Width="20">
<TextBlock Text="Title" Foreground="White"></TextBlock>
</Button>
<Button Background="Green">
<TextBlock Text="Title" Foreground="White"></TextBlock>
</Button>
<Button Background="Blue" Click="btnMenuItem_Click">
<TextBlock Text="Title" Foreground="White"></TextBlock>
</Button>
<Button Background="Blue" Click="btnMenuItem_Click">
<TextBlock Text="Title" Foreground="White"></TextBlock>
</Button>
<Button Background="Blue" Click="btnMenuItem_Click">
<TextBlock Text="Title" Foreground="White"></TextBlock>
</Button>
</StackPanel>
</Pivot.Title>
</Pivot>
</Grid>
I want five buttons in a row but these are already too wide for the screen (windows phone). Changing the width doesnt seem to have any effect (why is it there).
The textBlock control within the button the button is as wide as the text on it, but i dont seem to have any control on the width of the button. In HTML you only have padding or margin when you define it but in xaml it just seems to be there and for me its unclear how to undo that.
*****EDIT*****
After reading Rachel's reply i decided to start from the ground up.
Using the code below i still have no control over how wide the button is because it uses a certain amount of padding that i cant seem to remove. The button has a width of about 110 when i define a width lower than that it doesnt change. Margins and paddings of 0 have no effect at all (dont want to use negative values just yet because that doesnt seem very intuitive). So the code below is very simple but still the button takes up an amount of space that i dont have any control over. I cant imagine a reason why it was designed this way.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="400" />
</Grid.ColumnDefinitions>
<StackPanel Width="300" Background="Red" HorizontalAlignment="Left">
<Button Background="Blue" HorizontalAlignment="Left" Width="100" Margin="0" Padding="0">
<TextBlock Text="Title" Width="Auto" HorizontalAlignment="Left" />
</Button>
</StackPanel>
</Grid>
The type and size of the parent panel containing the control affects the size/layout of the child controls.
In your case, you have a Grid as your parent panel, and a Grid defaults to taking up all available space. In addition, children placed inside the grid default to taking up all available space as well unless you specify otherwise.
So your <Pivot> is being assigned a width equal to Grid.Width, and Pivot.Title sounds like it's being assigned a width equal to Pivot.Width, and StackPanel is being assigned a width equal to Pivot.Title.Width... you get the picture.
To specify that a control should not take up all available space, specify a HorizontalAlignment or VerticalAlignment property to tell it what side of the parent panel to dock the item on.
For example
<Pivot Grid.Row="1" HorizontalAlignment="Left">
or
<StackPanel OWidth="480" HorizontalAlignment="Left" ...>
If you're new to WPF's layout system, I would recommend reading through the codeproject article WPF Layouts: A Quick Visual Start to quickly learn what the main layout panels are for WPF.

How to avoid sizing grip overlap in Window

I made a WPF Window containing StatusBar with StatusBarItem and ProgressBar.
The Window has a property ResizeMode set to CanResizeWithGrip.
It shows the sizing grip properly, but it overlaps elements underneath:
How can I avoid this overlap? I can set right margin to the progress bar, but how large? I don't want to use any magic numbers or hardcoded values. It would be also nice to have this resolved purely in XAML.
You can change style for "Window" considering all wishes.
http://msdn.microsoft.com/en-us/library/aa969824(v=vs.110).aspx
or https://stackoverflow.com/a/8278917/3492412
Or can do something like this
<StatusBar VerticalAlignment="Bottom">
<StatusBarItem x:Name="statusbar" Background="Gray" HorizontalContentAlignment="Stretch">
<DockPanel>
<ResizeGrip DockPanel.Dock="Right" Visibility="Hidden" />
<ProgressBar Background="red" Height="20" Value="50" />
</DockPanel>
</StatusBarItem>
</StatusBar>

VerticalAlignment="Stretch" for label inside canvas doesn't work

How to use VerticalAlignment="Stretch" with a Label inside a Canvas? I'm trying to center the text "Cancel" in the button as in the code below. To use fixed height and width for the label isn't a desired option.
<Button Name="buttonCancel" Width="80" Height="40" IsCancel="True" Padding="0" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
<Canvas>
<Label Canvas.Top="0" Canvas.Left="0" Padding="0" FontSize="10">Esc</Label>
<Label VerticalContentAlignment="Center" HorizontalContentAlignment="Center" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">Cancel</Label>
</Canvas>
</Button>
Use a binding to the Canvas's ActualWidth:
<Canvas>
<Label Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type Canvas}}, Path=ActualWidth}">...</Label>
</Canvas>
But as mentioned above, if you are interested in dynamic stretching layouts, the Canvas is not the ideal choice of control.
A Canvas does not perform any scaling layout of its contents; if you want to scale the contents, you could use Grid in this case, which will, by default, scale both Label elements to fill the Content space.
Assuming you need the canvas for other objects that are of a fixed nature, you could overlay the Canvas on a Grid, and then put the labels in the grid. You can put the labels before the canvas to make them background z-index (overwritten by canvas objects) or after the canvas to make them higher z-index (will overwrite canvas objects). For example:
<Button Name="buttonCancel" Width="80" Height="40" IsCancel="True" Padding="0" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
<Grid>
<Label Padding="0" FontSize="10">Esc</Label>
<Label VerticalContentAlignment="Center" HorizontalContentAlignment="Center" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">Cancel</Label>
<Canvas>
<!-- Your Canvas content here -->
</Canvas>
</Grid>
</Button>
Repeating my solution from the comments, since (a) you really don't want a Canvas and (b) it sounds like this solved your problems, so I'll make it an answer where it will be more visible to others.
Canvas is meant for fixed-pixel-size layouts, which is probably the least common case. You should replace your Canvas with a Grid as shown below, so that both Labels are laid out dynamically (and independently) within the available space:
<Grid>
<Label Padding="0" FontSize="10">Esc</Label>
<Label VerticalAlignment="Center" HorizontalAlignment="Center">Cancel</Label>
</Grid>

WPF ListBox DataTemplate and Image Question

I have a ListBox with a StackPanel that contains an image and label.
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal" IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Image Source="{Binding Image}" Cursor="Hand" Tag="{Binding Link}" MouseLeftButtonDown="Image_MouseLeftButtonDown" ToolTip="Click to see this product on adidas.com" VerticalAlignment="Top" HorizontalAlignment="Left" />
<Label Content="{Binding Name}" Cursor="Hand" Tag="{Binding Link}" MouseLeftButtonDown="Label_MouseLeftButtonDown" VerticalAlignment="Bottom" Foreground="White" Style="{StaticResource Gotham-Medium}" FontSize="8pt" HorizontalAlignment="Center" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
I want to show a third image (glow.png) behind the currently moused over image. I can't seem to add a second image to the stack panel, and set it's visibility to hidden. I haven't even tackled the mouseover part yet.
Is adding another image inside the stack panel, and then setting it's visibility to visible the right approach on mouseenter, and then swapping back on mouseleave?
Thanks.
You certainly can have one image behind another. Instead of directly adding the image to your StackPanel, add a Grid and then add both images, like this:
<StackPanel Orientation="Vertical">
<Grid>
<Image Source="..." />
<Image Source="{Binding Image}" ... />
</Grid>
<Label Content="{Binding Name}" ... />
</StackPanel>
You might also like to look into Bitmap Effects, using which you can introduce a "glow" effect onto any WPF element.
Edit: Another way to achieve the effect you want (I believe) is to swap out the image's Source property in a trigger. I'm not going to try to write the XAML from memory here, but you could catch the IsMouseOver property for the image itself, and when it switches to True you could set its Source to the "glowing" version of the image.
Another possibility is to add a border to your image, set the color of the borderbrush to whatever you want and the opacity to 0. In your MouseEnter event handler set the opacity to 1.

Resources