I have search hint textbox
<TextBox
TextChanged="textboxsearch_TextChanged"
Grid.Column="4" Margin="0,0,10,10" Height="22" >
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="Text" Value="">
<Setter Property="Background" Value="{StaticResource SearchHint}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
<Setter Property="VerticalAlignment" Value="Bottom"/>
</Style>
</TextBox.Style>
</TextBox>
here is SearchHint style
<VisualBrush x:Key="SearchHint" Stretch="None">
<VisualBrush.Visual>
<TextBox FontStyle="Italic" Background="White" Foreground="Gray" Text="Enter search text…" />
</VisualBrush.Visual>
</VisualBrush>
The search box back ground is filled by the searchhint style. The problem I have now is how can I make the width of the visual brush fill the size of the textbox. Right now it fills only a portion of the textbox.
The Text="Enter search text…" has a white background but the rest of the textbox is gray. I wanted to have a white background with gray hint text.
Give the TextBox in the VisualBrush a large padding (to the right), and give the VisualBrush a left alignment:
<VisualBrush x:Key="SearchHint" Stretch="None" AlignmentX="Left">
<VisualBrush.Visual>
<TextBox FontStyle="Italic" Background="White" Foreground="Gray" Text="Enter search text…"
Padding="0,0,1000,0" />
</VisualBrush.Visual>
</VisualBrush>
Well for what you're trying you can bind the Width of the control in the VisualBrush to your actual target's ActualWidth
something like:
<VisualBrush x:Key="SearchHint"
Stretch="None">
<VisualBrush.Visual>
<TextBox Background="White"
FontStyle="Italic"
Foreground="Gray"
Width="{Binding ElementName=tb, Path=ActualWidth}"
Height="{Binding ElementName=tb, Path=ActualHeight}"
Text="Enter search text…" />
</VisualBrush.Visual>
</VisualBrush>
...
<TextBox Grid.Column="4"
Height="22"
TextChanged="textboxsearch_TextChanged"
x:Name="tb"
Margin="0,0,10,10">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="Text"
Value="">
<Setter Property="Background"
Value="{StaticResource SearchHint}" />
</Trigger>
<Trigger Property="IsKeyboardFocused"
Value="True">
<Setter Property="Background"
Value="White" />
</Trigger>
</Style.Triggers>
<Setter Property="VerticalAlignment"
Value="Bottom" />
</Style>
</TextBox.Style>
</TextBox>
However
What you're "functionally" trying to do is referred to commonly as "Watermark" / "Placeholder text" and it's much simpler to use that approach than have a complicated VisualBrush with an actual control being turned into a Brush. Just my opinion.
If you want to try the Watermark approach This Answer gives a good example for you to work with.
Related
I am trying to build a text filter for a list in a popup, and notify the user when the filter is active by changing the color of the button that opens the popup.
I am using an MVVM lite setup and a XAML style sheet to reference the desired styles. Up until this point I have created the popup and the controlling button, and I have been able to put a mouse over trigger on the button and have it work. However when I tried to have a datatrigger set to the value of the textbox in the popup, it does not respond at all.
Here is the XAML code in the View for the button and the popup:
<StackPanel Orientation="Horizontal" Grid.Column="1" HorizontalAlignment="Center" >
<TextBlock HorizontalAlignment="Center" Text="Filter Popup" />
<Button x:Name="PopUpControl" Tag="popup" Style="{StaticResource FilterButtonStyle}" Command="{Binding OpenPopupCommand}" IsEnabled="{Binding IsFilterEnabled, UpdateSourceTrigger=PropertyChanged}" Margin="2,1,2,1" VerticalAlignment="Top"/>
</StackPanel>
<Popup x:Name="textPopup" IsOpen="{Binding IsFilterPopupOpen, Mode=TwoWay}" PlacementTarget="{Binding ElementName=PopUpControl}" Placement="Bottom" Width="Auto" StaysOpen="False" Margin="2 2 2 2">
<TextBox x:Name="TextValue" Grid.Column="0" BorderThickness="1" Style="{StaticResource WatermarkedTextBox}" Margin="2,4" VerticalAlignment="Center" Tag="Text Filter" Text="{Binding FilterSearch, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"
<Button Grid.Column="4" Style="{StaticResource SearchIconStyle}" IsEnabled="{Binding FilterEnabled, Mode=TwoWay}" Command="{Binding ApplyFilterCommand}" Margin="19,6" Grid.ColumnSpan="2" />
</Grid>
</Popup>
Here is the style for the button:
<Style x:Key="SortButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Width" Value="15"/>
<Setter Property="Height" Value="15"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="Margin" Value="4,0,4,0" />
<Setter Property="Tag" Value="Default" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="border"
Padding="4,2"
CornerRadius="3"
Background="{DynamicResource PaleBlue}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
<Border.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_filter}" />
</Border.OpacityMask>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="{DynamicResource ColumnHeaderFilterColor}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
What I would like to happen, is when the element "TextValue" has a value in the Text field, the primary background color for the "border" changes color. Any help would be greatly appreciated.
You could use a DataTrigger that binds to the FilterSearch source property and sets a property if returns an empty string or null:
<ControlTemplate TargetType="Button">
<Border Name="border"
Padding="4,2"
CornerRadius="3"
Background="Green">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
<Border.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_filter}" />
</Border.OpacityMask>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding FilterSearch}" Value="">
<Setter TargetName="border" Property="Background" Value="{DynamicResource PaleBlue}" />
</DataTrigger>
<DataTrigger Binding="{Binding FilterSearch}" Value="{x:null}">
<Setter TargetName="border" Property="Background" Value="{DynamicResource PaleBlue}" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
I am new to wpf. Actully i want to change button icon(play.ico/stop.ico).
when i click the button it changes status(status is database column) value 'Online' to Offline, or Offline to Online.
It updating in database also but
I want to show when status is online buttton should show stop.ico and when I status is offline button should show play.ico.
How to achieve this? I tried with below code but its not working. please help and suggest what i am missing something.
//Xaml code
<StackPanel Margin="0 0 0 0" Grid.Column="5" Grid.Row="0" Grid.RowSpan="2">
<Button Name="Ignition_Button1" Click="Ignition_Button1_Click_1" Width="35" Height="35" Margin="16,5,16,0"
Style="{DynamicResource CircleButton}"
Command="{Binding StartStopCommand}">
<Button.ToolTip>
<ToolTip>
<StackPanel>
<TextBlock FontWeight="Bold"
Text="Start or Stop Control Center" />
</StackPanel>
</ToolTip>
</Button.ToolTip>
<StackPanel Orientation="Vertical">
<Rectangle Width="15" Height="15" StrokeThickness="0">
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="{StaticResource play.ico}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Status, UpdateSourceTrigger=PropertyChanged}" Value="Online">
<Setter Property="Fill" Value="{StaticResource stop.ico }" />
</DataTrigger>
<DataTrigger Binding="{Binding Status, UpdateSourceTrigger=PropertyChanged}" Value="Offline">
<Setter Property="Fill" Value="{StaticResource play.ico}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
</StackPanel>
</Button>
</StackPanel>
Several things I would suggest here.
Rather than ico which are bitmap and will have jaggies, I would recommend geometries and paths.
With a button which has two states you toggle between then a togglebutton is a good candidate.
Below I put my two geometries in resources of my togglebutton.
These are more usually put into a resource dictionary (along with the many other geometries used for iconography) and merged in app.xaml.
<ToggleButton IsChecked="True"
IsThreeState="False"
>
<ToggleButton.Resources>
<Geometry x:Key="StopGeom">
M0,0L32,0 32,32 0,32z
</Geometry>
<Geometry x:Key="PlayGeom">
M0,0L16,8 32,16 16,24 0,32 0,16z
</Geometry>
</ToggleButton.Resources>
<Path Fill="Black"
Stretch="Uniform"
Margin="4">
<Path.Style>
<Style TargetType="Path">
<Setter Property="Data" Value="{StaticResource PlayGeom}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, RelativeSource={RelativeSource AncestorType={x:Type ToggleButton}}}" Value="True">
<Setter Property="Data" Value="{StaticResource StopGeom}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
</ToggleButton>
This needs more work but should give you the idea of one way to do this.
For more about layout and geometries:
https://social.technet.microsoft.com/wiki/contents/articles/32610.wpf-layout-lab.aspx
I don't know how you're styling the shape of your button, but I use this one to emphasise to wpf newbies what lookless controls means:
https://social.technet.microsoft.com/wiki/contents/articles/29866.aspx
I have got a style as follows.
<TextBox HorizontalContentAlignment="Center" Text="{Binding IpAddress, Mode=TwoWay}" ToolTip="Ip Address of camera">
<TextBox.Style>
<Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Style.Resources>
<VisualBrush x:Key="CueBannerBrush" AlignmentX="Center" AlignmentY="Center" Stretch="None">
<VisualBrush.Visual>
<Label Content="Camera Ip Address" Foreground="Gray" Opacity="0.5" FontStyle="Italic" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
And I had kept it as a resource dictionary in a Skin.xaml file to be re-used as explained in the answer here.
But now I want the Content="Camera Ip Address" (the 7th line in the style) to be different for each textbox that I apply the style to. I saw SO answers this and this. These SO answers are suggesting the BasedOn attribute, but I am not sure how to apply this to my case. My case seems to be many levels deep. Can someone please suggest me how to achieve this.
Basically what I want is, for one textbox that I apply the Content should be Camera Ip Address, while for another textbox I want this content to be Camera Login. How do I achieve this?
You can set the content of that inner Label to the Tag property of the TextBox and then display it in the Label.
Like so:
<TextBox Tag="Whatever you want">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Resources>
<VisualBrush x:Key="CueBannerBrush">
<VisualBrush.Visual>
<Label Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=TextBox},Path=Tag,Mode=OneWay" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
</Style>
</TextBox.Style>
</TextBox>
I have a style guide from a designer for a button that looks like a hyperlink and I am trying to get as close to it as I can with WPF styles.
But I haven't been able to change the distance between the text and the underline.
I wanted to add images for comparision but unfortunately I haven't earned enough points to do so far.
Is there a way to change the distance between text and underline?
Here is the XAML code I have so far:
<Style x:Key="LinkButton" TargetType="ButtonBase">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ButtonBase">
<StackPanel Orientation="Horizontal">
<TextBlock Text="> "/>
<TextBlock TextDecorations="Underline">
<ContentPresenter/>
</TextBlock>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="{StaticResource LxGrayBrush}"/>
<Setter Property="FontSize" Value="12"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Foreground" Value="{StaticResource LxGreenBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
Use element syntax to add an instance of TextDecoration to the TextBlock.TextDecorations, then you can adjust the Location or PenOffset.
<TextBlock>
<TextBlock.TextDecorations>
<TextDecoration Pen="..." Location="..."/>
</TextBlock.TextDecorations>
</TextBlock>
(You may need to set the Pen via element syntax as well)
<TextBlock >
Here is my text to be displayed
<TextBlock.TextDecorations>
<TextDecoration PenOffset="3" PenOffsetUnit="Pixel"/>
</TextBlock.TextDecorations>
</TextBlock>
Adjusting PenOffset would increase/decrease the gap between text and the line.
You can do this by adding a Separator between them or by setting the Margin.
Separator:
<StackPanel Orientation="Horizontal">
<TextBlock Text="> "/>
<Separator Width="5" Visibility="Hidden" />
<TextBlock TextDecorations="Underline">
<ContentPresenter/>
</TextBlock>
</StackPanel>
Margin:
<StackPanel Orientation="Horizontal">
<TextBlock Text="> " Margin="0,0,5,0" />
<TextBlock TextDecorations="Underline">
<ContentPresenter/>
</TextBlock>
</StackPanel>
To have a line closer to the text than "Underline" there is "Baseline". It is much less flexible than the H.B. solution but also simpler.
<TextBlock TextDecorations="Baseline" />
How do I make WPF TextBox acted as a compact form?
This means that "label text" inside TextBox is hiding on the click or when there is "real text".
See working prototype
You can use a data trigger in the style for the TextBox, and set the background to something that includes your text. A sample that works simply would be this:
<TextBox>
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding Text, RelativeSource={RelativeSource Self}}" Value="">
<Setter Property="Background">
<Setter.Value>
<VisualBrush Stretch="None" AlignmentX="Left">
<VisualBrush.Visual>
<TextBlock Text="This is the label text" Foreground="Silver" />
</VisualBrush.Visual>
</VisualBrush>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
Tested in Kaxaml; the "label text" alignment isn't quite right, and you'd maybe want to refactor this into something more reusable for production code.
EDIT: to cover the "Hide on focus" scenario you'd need a more complicated trigger. Replace the datatrigger with this:
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Text, RelativeSource={RelativeSource Self}}" Value="" />
<Condition Binding="{Binding IsKeyboardFocused, RelativeSource={RelativeSource Self}}" Value="False" />
</MultiDataTrigger.Conditions>
<Setter Property="Background">
<Setter.Value>
<VisualBrush Stretch="None" AlignmentX="Left">
<VisualBrush.Visual>
<TextBlock Text="This is the label text" Foreground="Silver" />
</VisualBrush.Visual>
</VisualBrush>
</Setter.Value>
</Setter>
</MultiDataTrigger>