Inheriting values declared at UserControl instantiation - silverlight

First off, I apologize if this question has been asked before. I've done a bit of Google searching but I'm not really sure what the correct keywords are to find what I'm looking for.
Basically my problem is simple to understand. I have a Silverlight project and on the MainPage.xaml I have declared a UserControl and given it a height and a width.
<Grid>
<control:AlarmButton Height="50" Width="50" />
</Grid>
Now within AlarmButton I have a button that has its own Control Template which is set up the way I want. It has a content presenter within it right now.
<UserControl
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"
mc:Ignorable="d"
x:Class="Alarms.AlarmButton">
<UserControl.Resources>
<ControlTemplate x:Key="StatusButton" >
<Viewbox Stretch="Fill">
<Grid>
<Path x:Name="Base" StrokeThickness="1.0" Stroke="#ff000000" StrokeMiterLimit="1.0" Fill="#ff666666" Data="F1 M 99.500,99.500 L 0.500,99.500 L 0.500,0.500 L 99.500,0.500 L 99.500,99.500 Z"/>
<Path x:Name="Interior" Opacity="0.5" StrokeThickness="1.0" Stroke="#ff191919" StrokeMiterLimit="1.0" Data="F1 M 97.500,97.500 L 2.500,97.500 L 2.500,2.500 L 97.500,2.500 L 97.500,97.500 Z">
<Path.Fill>
<LinearGradientBrush MappingMode="Absolute" StartPoint="2.500,2.499" EndPoint="97.500,97.499">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.00" Color="#3FFFFFFF"/>
<GradientStop Offset="0.151" Color="Transparent"/>
<GradientStop Offset="1.00" Color="#BFFFFFFF"/>
<GradientStop Color="#53FFFFFF" Offset="0.655"/>
</LinearGradientBrush.GradientStops>
<LinearGradientBrush.Transform>
<MatrixTransform Matrix="1.000,0.000,-0.000,-1.000,0.000,100.000" />
</LinearGradientBrush.Transform>
</LinearGradientBrush>
</Path.Fill>
</Path>
<Path x:Name="LargeShader" Opacity="0.1" Fill="#ffffffff" Data="F1 M 94.667,18.667 L 94.667,94.667 L 6.333,94.667 C 6.333,94.667 94.667,67.348 94.667,18.667 Z"/>
<Path x:Name="SmallShader" Opacity="0.1" Fill="#ffffffff" Data="F1 M 94.667,43.667 L 94.667,94.667 L 20.333,94.667 C 20.333,94.667 94.667,76.334 94.667,43.667 Z"/>
<ContentPresenter x:Name="contentPresenter" Height="{TemplateBinding Height}" Width="{TemplateBinding Width}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
</Viewbox>
</ControlTemplate>
</UserControl.Resources>
<Grid >
<Button Template="{StaticResource StatusButton}" >
<TextBlock Text="this is a text box"
TextTrimming="WordEllipsis" />
</Button>
</Grid>
</UserControl>
Later on I'm going to bind the Text property to a DependencyProperty so I can use this button with multiple text. What I want to happen is if the text is too big it will ellipse it and not have the box change or the textblock overflow. I just need to bind the height and width of the TextBlock to some values to contain it.
My question is this; is it possible for the TextBlock to bind its height and width to the values as declared in the MainPage.xaml? Or is this more complicated than I imagine? Is there a better way to go about this?
EDIT
This might give a little more info on what I'm trying to accomplish. This is my "button" with RobSiklos' changes

I think the problem has something to do with the Viewbox, which is telling the TextBlock that it has as much room as it wants.
Probably removing the Viewbox will solve the issue (or at least take the ContentPresenter out of the Viewbox)

I'm not sure I completely understand. Are you trying to make the text ellipse because you don't want the text block to grow if the text is too big? If so, you could use a converter (in the binding statement of the Text property) to have the the converter return the full text value if the text is under a certain length, or have the converter show an ellipse if the text is over that value.

This ought to work:-
<Grid x:Name="LayoutGrid">
<Button Template="{StaticResource StatusButton}" >
<TextBlock Text="this is a text box" TextTrimming="WordEllipsis"
Width="{Binding Parent.Width, ElementName=LayoutRoot}"
Height="{Binding Parent.Height, ElementName=LayoutRoot}" />
</Button>
</Grid>
It assumes that a Width and Height will be specified. An alternative would be to be to use the SizeChanged event of the UserControl to assign values of Width and Height directly.

Related

WPF / Xaml, vertical aligment of LineGeomtry inside grid not working properly

I try to get into creation of custom controls with for WPF. I found many good
tutorials and advises on the web so I started width a really simple example to get
my hands dirty and get some practice. I figured out that the issue stumbled across
is not really related to the subject of custom controls. So I extracted the xaml code to a simple wpf form.
<Window x:Class="WpfVerticalAigmentTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="200" Width="200">
<Grid>
<Grid Height="40" Background="LightCyan" VerticalAlignment="Center">
<Path Stroke="Red"
StrokeThickness="20" VerticalAlignment="Center" >
<Path.Data>
<LineGeometry StartPoint="0,0" EndPoint="100,0"></LineGeometry>
</Path.Data>
</Path>
</Grid>
</Grid>
My expectation was to get a line centered in the grid and claiming the half of the stroke thickness on each side from the center. But as the linked image shows differs from my expectation.
"Resulting visualization"
So it look like I missed a detail about the line shape or linegeomtry. How do I get the the line displayed as shown in the following image?
"Expected result"
You need to match the Width and Height of the LineGeometry to the Width and Height of the Path and set the VerticalAlignment property to Bottom:
<Grid Height="20" Width="200" Background="LightCyan" VerticalAlignment="Center">
<Path Stroke="Red" StrokeThickness="20" VerticalAlignment="Bottom">
<Path.Data>
<LineGeometry StartPoint="0,0" EndPoint="200,0"></LineGeometry>
</Path.Data>
</Path>
</Grid>
If your goal is your the expectaions, and not the way how u have reached this, I could prefer to you this:
<Grid>
<Grid Height="40" Background="LightCyan" VerticalAlignment="Center">
<Border BorderThickness="10" VerticalAlignment="Center" BorderBrush="Red" />
</Grid>
</Grid>
The problem here is that the starting point of the XY Coordinates of the Path starts on the top left, and the stroke expands in both directions but thereby only makes the Path bigger to the bottom (I can't really tell you why, but that's just what seems to happen).
You can see this pretty good in the Design View:
To work around this simply move your Y Coordinates down half of the stroke size.
<Grid Height="40"
VerticalAlignment="Center"
Background="LightCyan">
<Path VerticalAlignment="Center"
Stroke="Red"
StrokeThickness="20">
<Path.Data>
<LineGeometry StartPoint="0,10" EndPoint="100,10" />
</Path.Data>
</Path>
</Grid>
Or wrap it in another control (Canvas is the commonly used controls for Paths) with the desired height:
<Grid Height="40"
VerticalAlignment="Center"
Background="LightCyan">
<Canvas Height="20" VerticalAlignment="Center">
<Path Stroke="Red"
StrokeThickness="20">
<Path.Data>
<LineGeometry StartPoint="0,10" EndPoint="100,10" />
</Path.Data>
</Path>
</Canvas>
</Grid>
And you are good to go:

Set the icon color in a MahApp application

I want to set the icon color in a MahApp application, but the brush is not working. In this example the icoun should be white, but still it is black.
<Rectangle Width="20" Height="20">
<Rectangle.Resources>
<SolidColorBrush x:Key="BlackBrush" Color="White" />
</Rectangle.Resources>
<Rectangle.Fill>
<VisualBrush Stretch="Fill" Visual="{StaticResource appbar_cupcake}" />
</Rectangle.Fill>
</Rectangle>
This is the resource icons.xml file in my app.
<Canvas Width="48" Height="48" Clip="F1 M 0,0L 48,0L 48,48L 0,48L 0,0" x:Key="appbar_cupcake">
<Path Width="24" Height="25" Canvas.Left="13" Canvas.Top="11" Stretch="Fill" Fill="{DynamicResource BlackBrush}" Data="F1 M 32,14C 33.1046,14 34,14.8954 34,16C 34,16.3643 33.9026,16.7058 33.7324,17L 34,17C 35.1046,17 36,17.8954 36,19C 36,20.1046 35.1046,21 34,21L 35,21C 36.1046,21 37,21.8954 37,23C 37,24.1046 36.1046,25 35,25L 15,25C 13.8954,25 13,24.1046 13,23C 13,21.8954 13.8954,21 15,21L 16,21C 14.8954,21 14,20.1046 14,19C 14,17.8954 14.8954,17 16,17L 16.2676,17C 16.0974,16.7058 16,16.3643 16,16C 16,14.8954 16.8954,14 18,14C 19,14 21,12 25,11C 29,14 31,14 32,14 Z M 15,26L 35,26L 32,36L 18,36L 15,26 Z " />
</Canvas>
What I'm doing wrong?
If you want to dynamically set the Fill color, you can do that by setting the Fill property. As you can see, you are already using the Fill property for the VisualBrush. Fortunately you can use the VisualBrush also in the OpacityMask property.
<Rectangle Fill="Black">
<Rectangle.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_cupcake}" Stretch="Fill" />
</Rectangle.OpacityMask>
</Rectangle>
Hope that helps.

XAML - How to get the name of one element in an other view

I have a component which call 2usercontrols.
Usercontrols1 :(code part)
<StackPanel Name="NeedThisName" >
</StackPanel>
Usercontrols2 :(code part)
<Button >
<Button.Template>
<ControlTemplate>
<Rectangle >
<Rectangle.Fill>
<VisualBrush Visual="{Binding ElementName=????}" Opacity="0.75" Stretch="None" >
<VisualBrush.RelativeTransform>
<TransformGroup>
<ScaleTransform ScaleX="0.5" ScaleY="0.5" />
</TransformGroup>
</VisualBrush.RelativeTransform>
</VisualBrush>
</Rectangle.Fill>
</Rectangle>
</ControlTemplate>
</Button.Template>
I would like to get the name in usercontrol1 ("NeedThisName") to specify to the Visual property of the visualbrush.
You should not access controls of one usercontrol from another.
Try to comminicate between them only using (Dependency-)properties and / or databinding to ViewModel classes. For example, your user control could have a property "RectangleFill" which the fill of the rectangle is bound to.

How to position UserControl in the parent canvas

I want to place this UserControl at Canvas.Left="168", Canvas.Top="213".
However, the control appears at a corner. What should I do?
If I put the values at the point of usage for this class, the values are returned as NaN
In that case how can I get the correct Left and Top Values?
Usage:
<Canvas x:Name="DesignerCanvas"
ClipToBounds="True"
SnapsToDevicePixels="True">
<Gr:BareNode />
</Canvas>
UserControl:
<UserControl x:Class="DiagramDesigner.BareNode"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<ContentControl Width="50"
Height="50"
Padding="2"
Canvas.Left="168" Canvas.Top="213">
<Ellipse IsHitTestVisible="False" >
<Shape.Fill>
<RadialGradientBrush Center="0.2, 0.2" GradientOrigin="0.2, 0.2" RadiusX="0.8" RadiusY="0.8">
<GradientStop Color="LightBlue" Offset="0"/>
<GradientStop Color="Blue" Offset="0.9"/>
</RadialGradientBrush>
</Shape.Fill>
</Ellipse>
</ContentControl>
</Grid>
</UserControl>
I'm not sure if you tried this or not, but just from looking at the XAML it appears that you are trying to set the position of the user control inside the user control. That won't work. You need to put it where you use the user control
<Canvas x:Name="DesignerCanvas"
ClipToBounds="True"
SnapsToDevicePixels="True">
<Gr:BareNode Canvas.Left="168" Canvas.Top="213"/>
</Canvas>
Take the Canvas.Left="168" Canvas.Top="213" part out of the ContentControl declaration of inside the user control.

How do I completely replace the content of a WPF button with a graphic path?

I've deconstructed a standard WPF button using Blend and have managed to create a nicely styled button, but I cannot figure out how to make the path fill the interior of the button space (the button width and height). I am also not sure if I need to specify ContentPresenter or even if it is correct. I am after the text in the middle of the button (as normal) but with my graphic path behind it.
Can anyone give me feedback on how to accomplish this? The style is defined as;
<ControlTemplate x:Key="CurvedButton" TargetType="{x:Type Button}">
<Grid>
<Path Fill="#ff951c1f" Data="F1 M 64,16 C 64,24 56,31 48,31 L 15,31 C 7,31 0,24 0,16 C 0,7 7,0 15,0 L 48,0 C 56,0 64,7 64,16 Z" />
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Width="Auto" />
</Grid>
</ControlTemplate>
The usage of this button is;
<StackPanel>
<Button Template="{StaticResource CurvedButton}" FontFamily="MS Trebuchet" FontSize="40" Width="200" Height="120" Foreground="Black">XXXXXXXXXXX</Button>
</StackPanel>
When all is done, it should just look like a curvy red button.
Thanks in advance
Ryan
There are a couple things you can do to get the results you're looking for.
Place the path in a viewbox and have it stretch to fill:
<ControlTemplate x:Key="CurvedButton" TargetType="{x:Type Button}">
<Grid>
<Viewbox Stretch="Fill">
<Path Fill="#ff951c1f" Data="F1 M 64,16 C 64,24 56,31 48,31 L 15,31 C 7,31 0,24 0,16 C 0,7 7,0 15,0 L 48,0 C 56,0 64,7 64,16 Z" />
</Viewbox>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Width="Auto" />
</Grid>
</ControlTemplate>
Use a border instead of a path:
<ControlTemplate x:Key="CurvedButton" TargetType="{x:Type Button}">
<Grid>
<Border CornerRadius="40" Background="#ff951c1f">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Width="Auto" />
</Border>
</Grid>
</ControlTemplate>

Resources