Visual brush weird behavior - wpf

I have a textbox and a rectangle. The rectangle updates itself when textbox content changes. I'm painting the rectangle fill with visual brush. The problem is that the visual brush don't match the textbox's actual look. What should I do. Here's my code:
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBox Name="txtBox"/>
<Rectangle Height="{Binding ElementName=txtBox, Path=ActualHeight}"
Width="{Binding ElementName=txtBox, Path=ActualWidth}">
<Rectangle.Fill>
<VisualBrush Visual="{Binding ElementName=txtBox}"/>
<Rectangle.Fill>
<Rectangle.LayoutTransform>
<ScaleTransform ScaleY="-0.75"/>
</Rectangle.LayoutTransform>
</Rectangle>
</StackPanel>
Here I wrote "Visual Brush",
then deleted few chars and look what I got:

Made a small change to your Xaml based on the information in your comment. The problem seems to be that the TextBlock doesn't have a Background so I guess that the VisualBrush just finds the visible part of the TextBlock for rendering and then stretches it to the full length of the TextBlock based on the Bindings.
The following Xaml works fine when the TextBlock has Background="Transparent" but reproduces your problem without it
Update: In the chat, the OP found that the Width Binding kept the TextBox from shrinking when deleting characters. So removing the Width binding fixes the centering issue as well.
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBox Name="txtBox"/>
<TextBlock Name="textBlock" Text="{Binding ElementName=txtBox, Path=Text}"
Background="Transparent"/>
<Rectangle Height="{Binding ElementName=textBlock, Path=ActualHeight}">
<Rectangle.Fill>
<VisualBrush Visual="{Binding ElementName=textBlock}"/>
</Rectangle.Fill>
<Rectangle.LayoutTransform>
<ScaleTransform ScaleY="5"/>
</Rectangle.LayoutTransform>
</Rectangle>
</StackPanel>

Related

How to add Text under a MahApps MetroCircleButtonStyle icon?

I am using the MahApps Metro controls in a WPF application with their FlyOut control on the bottom of the window. I am using their MetroCircleButtonStyle button like so:
<Button Width="55"
Height="55"
VerticalAlignment="Top"
Style="{DynamicResource MetroCircleButtonStyle}">
<Rectangle Width="20"
Height="20">
<Rectangle.Fill>
<VisualBrush Stretch="Fill"
Visual="{StaticResource appbar_city}" />
</Rectangle.Fill>
</Rectangle>
</Button>
My question is how do I add Text below these icons in the flyout?
Steve
something like:
<Button Width="55"
Height="55"
VerticalAlignment="Top"
Style="{DynamicResource MetroCircleButtonStyle}">
<StackPanel Orientation="Vertical">
<Rectangle Width="20"
Height="20">
<Rectangle.Fill>
<VisualBrush Stretch="Fill"
Visual="{StaticResource appbar_city}" />
</Rectangle.Fill>
</Rectangle>
<TextBlock Text="Hello" />
</StackPanel>
</Button>
Update:
MetroCircleButtonStyle by itself does not accomodate for Text outside the Ellipse. It's Template is pretty much a Grid with 1 cell and 3 children on top of each other(Ellipse, Another Ellipse and top-most is the ContentPresenter). Text inside does not actually respond to any state change either, So text outside with this Style is as good as wrapping the Button without text with a TextBlock in say a StackPanel.
What you're looking for, you could use the AppBarButton. Do note the documentation states, Due to issues with this control, AppBarButton is due to be removed for v1.0 so use that as an example and build up your own control with a similar Style. Probably drop the ViewBox, if your Button sizes are fixed.
From Viv's answer, you can add margin on the textbox element to push the label down:
<Button Width="55"
Height="55"
VerticalAlignment="Top"
Style="{DynamicResource MetroCircleButtonStyle}">
<StackPanel Orientation="Vertical">
<Rectangle Width="20"
Height="20">
<Rectangle.Fill>
<VisualBrush Stretch="Fill"
Visual="{StaticResource appbar_city}" />
</Rectangle.Fill>
</Rectangle>
<TextBlock Text="Hello" Margin="0, 20, 0, 0" />
</StackPanel>
</Button>

TextBlock Background Property removing stretch

I have a TextBox defined as this:
<TextBox>
<TextBox.Background>
<VisualBrush>
<VisualBrush.Visual>
<StackPanel>
<TextBlock Background="Blue" Opacity="0.5" Text="155"/>
</StackPanel>
</VisualBrush.Visual>
</VisualBrush>
</TextBox.Background>
</TextBox>
It looks like this:
However, when I remove the Background property, the text stretches like this:
Is there any way to add the background without changing the way the text looks?
If you use Background="Transparent" it will use the same layout but with no background color. Is that what you're trying to do?
a workarround of this problem which i don't know why it occurs would be to remove Background property from textblock and put it behind it like this
<Grid>
<Rectangle Fill="Blue"/>
<TextBox Height="100">
<TextBox.Background>
<VisualBrush Stretch="Fill" TileMode="None" AlignmentX="Left" AlignmentY="Top">
<VisualBrush.Visual>
<StackPanel>
<TextBlock Margin="0" Padding="0" Opacity="0.5" Text="155"/>
</StackPanel>
</VisualBrush.Visual>
</VisualBrush>
</TextBox.Background>
</TextBox>
</Grid>

wpf scale to textBox, textBox can not display cursor when i click textBox

First, I Zoom(ScaleTransform) the TextBox, then mouse to click on the TextBox. Sometimes can display the cursor, and sometimes can notdisplay the cursor. Looking for a solution to solution to the problem. I hope that I can show the cursor after I scale the TextBox.
<Grid>
<StackPanel>
<TextBox Width="200"></TextBox>
<TextBox Width="100"></TextBox>
<TextBox Width="300"></TextBox>
<TextBox Width="100"></TextBox>
<TextBox Width="100"></TextBox>
<TextBox Width="100"></TextBox>
</StackPanel>
<Grid.LayoutTransform>
<ScaleTransform ScaleX="0.3" ScaleY="0.65"></ScaleTransform>
</Grid.LayoutTransform>
</Grid>
A TextBox, especially a TextBox, is going to look bad and behave badly when scaled down. If you want your TextBox to look good and behave well, then use FontSize to reduce it and your font rendering and your cursor management will work better.
From an msdn answer I found:
The best workaround I work out is to apply an inverse transform on the TextBox and change the FontSize against the transform scale. You can wrap the TextBox with a Grid to maintain it's layout.
You can use the following code to see the effect. The FontSize in this sample is hardcoded to 10. You can use DataBinding to bind it to the scaletransform and use a converter to calculate a font size.
<Grid Background="AliceBlue">
<StackPanel>
<Border Height="100">
<Canvas>
<TextBox Canvas.Left="50" Canvas.Top="40" Width="500" Height="100" Background="Silver" Text="A Quick Red Fox Jumped Over A Lazy Brown Dog." FontSize="20"/>
<Canvas.RenderTransform>
<ScaleTransform ScaleX="0.5" ScaleY="0.5"/>
</Canvas.RenderTransform>
</Canvas>
</Border>
<Border Height="100">
<Canvas>
<Grid Canvas.Left="50" Canvas.Top="40" Width="500" Height="100">
<TextBox Background="Silver" Text="A Quick Red Fox Jumped Over A Lazy Brown Dog." FontSize="10" LayoutTransform="{Binding ElementName=scale, Path=Inverse}"/>
</Grid>
<Canvas.RenderTransform>
<ScaleTransform x:Name="scale" ScaleX="0.5" ScaleY="0.5"/>
</Canvas.RenderTransform>
</Canvas>
</Border>
You can see the full thread here: http://social.msdn.microsoft.com/Forums/en/wpf/thread/aeaa3e28-a7da-4208-9676-771231c1a954?prof=required

Binding to ActualHeight does not work

I tried to create a custom control, having a semitransparent rounded background:
<Canvas>
<TextBlock x:Name="StopText" Text="Some test text"/>
<Rectangle Fill="SkyBlue"
Width="{Binding Source=StopText, Path=ActualHeight}"
Height="20"
RadiusX="5" RadiusY="5" Opacity="0.2"/>
</Canvas>
The problem is that I can't, probably, bind to the ActualHeight/ActualWidth properties, cause they are not dependency ones.
What to do to mantain the rectangle and textbox of same size?
The correct binding is to use ElementName, not Source, when binding to another element:
<Canvas>
<TextBlock x:Name="StopText" Text="Some test text"/>
<Rectangle Fill="SkyBlue"
Width="{Binding ElementName=StopText, Path=ActualHeight}"
Height="20"
RadiusX="5" RadiusY="5" Opacity="0.2"/>
</Canvas>
Also, you do realize that you are binding the width of the Rectangle to the Height of the TextBlock, right?
If this is really the way you want to set up your control, you will want to bind the Rectangle's Width to the TextBlock's ActualWidth, and Height to ActualHeight.
UPDATE
Per the comments below, here is an implementation using a Grid with no binding:
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBlock x:Name="StopText" Text="Some test text"/>
<Rectangle Fill="SkyBlue"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
RadiusX="5" RadiusY="5" Opacity="0.2"/>
</Grid>
Grid and Canvas use different layout systems, and since you aren't using the functionality the Canvas provides, Grid is the better choice.
The big difference in the child elements is that the Rectangle now just uses Horizontal and VerticalAlignment to Stretch across the entire Grid, instead of worrying about the sizes of anything.

WPF Scaling Issue

I am perplexed with an issue that I am experiencing, using ScaleTransform. I have a Grid with a fixed width and height. The grid contains one child, a Rectangle. The Rectangle's Fill is a VisualBrush whose Visual binds to a canvas outside of the grid, whose dimensions are rather large. On the rectangle, I use a ScaleTransform, with ScaleX and ScaleY both being set to 0.18. Essentially, I am trying to scale the Rectangle's visual down to fit within my grid. What appears to be happening is that the Grid itself is being scaled down, resulting in a much smaller result than what I want. I have included the code below. Just as a point of reference, the height and width that the rectangle binds do are essentially 900 by 600, respectively. Any pointers as to what I might be doing wrong would be greatly appreciated.
<Grid Height="225" Width="200" Grid.Row="0" HorizontalAlignment="Left" VerticalAlignment="Top" x:Name="PART_Content">
<Rectangle Height="{Binding Path=ActualHeight}" Width="{Binding Path=ActualWidth}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Rectangle.Fill>
<VisualBrush Visual="{Binding}"/>
</Rectangle.Fill>
<Rectangle.RenderTransform>
<ScaleTransform ScaleX="0.183" ScaleY="0.183"/>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
Can you post the XAML for the Canvas element? I tried the following and I am getting the behavior you are going for (the rectangle is scaled and the grid is sized correctly)
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid ShowGridLines="True" Height="225" Width="200" Grid.Row="0" HorizontalAlignment="Left" VerticalAlignment="Top" x:Name="PART_Content">
<Rectangle Height="{Binding Path=ActualHeight}" Width="{Binding Path=ActualWidth}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Rectangle.Fill>
<VisualBrush Visual="{Binding ElementName=theCanvas}"/>
</Rectangle.Fill>
<Rectangle.RenderTransform>
<ScaleTransform ScaleX="0.183" ScaleY="0.183"/>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
<Canvas x:Name="theCanvas" Grid.Row="1">
<Rectangle Fill="Brown" Height="300" Width="300" />
</Canvas>
</Grid>
What is ActualWidth and ActualHeight? Unless I am mistaken the ActualHeight and ActualWidth properties as they normally mean in WPF are not DP's and you cannot bind to them. As has been pointed out below these are readonly dependency properties. Assuming this is in a CustomControl style Binding should be changed to TemplateBinding first.
I removed the bindings and essentially created a static version of your XAML which looks just fine. Since you have Part_Content defined for the grid, I am curious, is this xaml part of a custom control style? Is the code of the CustomControl manipulating the grid via PART_Content?
<Grid Height="225" Width="200" Grid.Row="0" HorizontalAlignment="Left" VerticalAlignment="Top" x:Name="PART_Content" Background="Red">
<Rectangle Height="225"
Width="200"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Fill="Blue">
<Rectangle.RenderTransform>
<ScaleTransform ScaleX="0.183" ScaleY="0.183"/>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>

Resources