Creating Layered Custom Control Templates (WPF 4 / .net 4.0 / C#) - c#

I need some help in trying to recreate the following style:
The sea of red can be ignored because it's just the background the textbox is sitting on.
To create the textbox I use the following xaml:
<TextBox Name="tbSorageName"
Grid.Column="1"
Width="250"
Height="30"
Margin="0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
IsReadOnly="True"
Style="{StaticResource MainTextBoxStyle}"
Text="{Binding SelectedStorage.Name,
Mode=OneWay,
UpdateSourceTrigger=PropertyChanged}" />
To style it, I used the following style:
<Style x:Key="MainTextBoxStyle" TargetType="TextBox">
<Setter Property="FontSize" Value="16" />
<Setter Property="Foreground" Value="Snow" />
<Setter Property="FontFamily" Value="Calibri" />
<Setter Property="TextAlignment" Value="Center" />
<Setter Property="Background" Value="{DynamicResource MainTextBox_BGBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource MainTextBox_BorderBrush}" />
<Setter Property="BorderThickness" Value="2" />
<Setter Property="TextAlignment" Value="Left" />
</Style>
The Brushes I use are:
<SolidColorBrush x:Key="MainTextBox_BGBrush" Color="#3A3A3A" />
<SolidColorBrush x:Key="MainTextBox_BorderBrush" Color="#656565" />
That creates the basic textbox I use in my application, but I want to take my design much further by floating some meaningful text that describes the contents of textbox on the right hand side of the text box - So it should be anchored to the right hand side.

You can do this easily via 2 approaches.
1.Create a user control that consists of a textbox and a textblock. The Xaml for the UserControl would look similar to the following
<Grid Width="{Binding Path=Width, ElementName=tbSorageName}" Height="{Binding Path=Height, ElementName=tbSorageName}">
<TextBox Name="tbSorageName"
Grid.Column="1"
Width="250"
Height="30"
Margin="0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
IsReadOnly="True"
Style="{StaticResource MainTextBoxStyle}"
Text="hello" />
<TextBlock HorizontalAlignment="Right" Margin="5" Foreground="Red" FontStyle="Italic">Name</TextBlock>
</Grid>
2.Overlay an Adorner on the textbox and draw the description over the Textbox yourself via an OnRender Override.
I would go with the Usercontrol approach since that is cleaner and easier to maintain.

Related

WPF ToolTip Text Alignment

I have the following ListViewItem:
<GridViewColumn Width="{Binding ActualWidth,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}},
Converter={StaticResource MathConverter}, ConverterParameter=(x/10)*1}">
<GridViewColumn.Header>
<GridViewColumnHeader Content=" Total Fees "
HorizontalContentAlignment="Right" />
</GridViewColumn.Header>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding GarnishmentTotals.TotalFees, StringFormat={}{0:c}}"
TextAlignment="Right" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
The Style for this item is as follows:
<Style x:Key="MultipleGarnishmentsStyle" TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding Garnishments.Count, Converter={StaticResource GreaterThanEqualToBooleanConverter}, ConverterParameter=2}" Value="True"
h:TriggerTracing.TriggerName="MultipleGarnishmentsStyle_Trigger1"
h:TriggerTracing.TraceEnabled="True">
<!-- Leave the content alone and just change the format string -->
<Setter Property="TextBlock.FontWeight" Value="UltraBold" />
<Setter Property="ToolTip" Value="Employee has multiple garnishments. Double click to view details." />
</DataTrigger>
</Style.Triggers>
</Style>
I am having an issue with the alignment of the text within the ToolTip.
The text seems to be using the ListViewItems text alignment (Right). I have tried adding the following properties to teh style but nothing changes:
<Setter Property="TootlTip.HorizontalAlignment" Value="Left" />
<Setter Property="TootlTip.HorizontalContentAlignment" Value="Left" />
<Setter Property="TootlTip.Width" Value="300" />
Is there a way to either increase the ToolTip width so there is no wrapping of the text or make the ToolTip text left aligned.
I got the same problem and after some digging (RibbonToolTip is inheriting alignment from a textbox), I found a solution. It maybe late, but it would benefit others.
What you need to do is to setup you ToolTip style like this:
<Style TargetType="ToolTip">
<Setter Property="TextBlock.TextAlignment" Value="Left"/>
</Style>
Since Tooltip is a ContentControl you can customize its content as you want. Consider the following example:
<Grid>
<Button Content="Hi there!">
<Button.Style>
<Style TargetType="Button">
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip MaxWidth="100" HorizontalContentAlignment="Center">
<TextBlock Text="fsdfasdfasdfasdfasdfasdfadsfasdf fadsfadsf adfa fdasfasdfasdfa adfasd" TextAlignment="Center" HorizontalAlignment="Center" TextWrapping="Wrap"/>
</ToolTip>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
</Grid>
You can play around with the content's properties (in this case the TextBlock) in order to achieve the final look you want.

Bring textbox on top of canvases below it

I have three canvases and each one contains textboxes.
The first canvas contains a textbox bigger than the canvas and should be on top of the below canvases.
I tried to use z-index but it seems canvases are always on top on the textboxes.
You could explictly create the item containers, i.e. ListBoxItems.
The ListBoxItems will be direct child elements of the ListBox's ItemsPanel and hence have a common parent element, which is required to make the ZIndex property work:
<ListBox>
<ListBoxItem Panel.ZIndex="1">
<Canvas ...>
...
</Canvas>
</ListBoxItem>
<ListBoxItem>
<Canvas ...>
...
</Canvas>
</ListBoxItem>
<ListBoxItem>
<Canvas ...>
...
</Canvas>
</ListBoxItem>
</ListBox>
I would also apply some styling to make your code way shorter and easier to maintain. Should look kinda like that before applying Clemenses solution:
<ListBox>
<ListBox.Resources>
<Style TargetType="{x:Type Canvas}">
<Setter Property="Width" Value="500" />
<Setter Property="Background" Value="Blue" />
<Setter Property="Height" Value="40" />
</Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Width" Value="30" />
<Setter Property="Canvas.Top" Value="10" />
<Setter Property="Height" Value="20" />
</Style>
</ListBox.Resources>
<Canvas Name="firstCanvas"
Top="80"
Left="100"
ZIndex="3">
<TextBox Name="BigText"
Background="White"
Canvas.ZIndex="6"
Canvas.Left="50"/>
<TextBox Canvas.Left="100"/>
<TextBox Canvas.Left="150"/>
<TextBox Canvas.Left="200"/>
</Canvas>
<Canvas Top="80"
Left="100"
ZIndex="1">
<TextBox Canvas.Left="100"/>
<TextBox Canvas.Left="150"/>
<TextBox Canvas.Left="200"/>
</Canvas>
<Canvas Top="80"
Left="100"
ZIndex="2">
<TextBox Canvas.Left="100"/>
<TextBox Canvas.Left="150"/>
<TextBox Canvas.Left="200"/>
</Canvas>
</ListBox>

WPF: Content of textbox/Combobox goes beyond window screen

I have a textbox/combobox displaying a particular path and both the textbox and combobox are already set to change size according to their contents. If the path is very long, it goes beyond the window screen and the "browse button" I have given gets hidden.(refer image for clarity).Note:I have this problem for both text & comboboxes.
Here's the snippet of a particular case:
<Label Content="_Layout Report Output Path:" Grid.Row="5" Target="{Binding ElementName=TxtLytRepPath}"/>
<StackPanel Grid.Row="5" Grid.Column="1" Orientation="Horizontal">
<ComboBox Name="CmbLytRepPath" Grid.Column="1" Text="{Binding LayoutReportPath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsEditable="True" IsReadOnly="True"/>
<Button Name="BtnLytRepPath" Style="{StaticResource BrowseButton}"/>
</StackPanel>
</Label>
Button Style:
<Style TargetType="Button" x:Key="BrowseButton">
<Setter Property="Content" Value="..."/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="MinHeight" Value="23"/>
<Setter Property="Width" Value="40"/>
</Style>
I cannot use a wrap panel as its makes the UI bad.Please suggest me some solution.
In your example, you close twice the label.
I think you will try with a dockpanel
<DockPanel Grid.Row="5" Height="??? if need">
<Label DockPanel.Dock="Left" Content="_xxx"/>
<Button DockPanel.Dock="Right" Style=” ”/>
<ComboBox />
</DockPanel>
Regards

Using custom properties in WPF styles

I have this text box:
<TextBox/>
I want to add a watermark to it to say, Enter your message here...
Since its not supported out of the box, this successfully does the trick:
<Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Style.Resources>
<VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
<VisualBrush.Visual>
<Label Content="Enter your message here..." Foreground="LightGray" Padding="10 0 0 0" />
</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>
But is there a way to extend TextBox with a XAML property for WatermarkText, as follows and have my style pick it up and use it, or is there some other way to do it (C#, etc.)?
<TextBox WatermarkText="Enter your message here..."/>
The best way to do this is using Attached Dependency Properties that you can bind in the style. Just keep in mind that binding an attached dependency property is
Text={Binding (AttachedPropertyName)}
The () make the trick.
Have a look at Mahapps. It's a nice design framework and providing a TextBoxHelper class doing all this. It's open source so you can see how it is implemented using attached properties.
The easiest way to do what I need is to just put a label in the same position as the text box without hit test visibility in the .xaml:
<TextBox Name="Username" Grid.Row="2" Height="40" FontFamily="Segoe UI" FontSize="20" VerticalContentAlignment="Center" TextChanged="Username_TextChanged"/>
<Label Name="UsernameLabel" Content="Username" Grid.Row="2" FontFamily="Segoe UI" FontSize="20" Foreground="LightGray" Padding="5" IsHitTestVisible="False" />
In the .cs:
private void Hostname_TextChanged(object sender, TextChangedEventArgs e)
{
UpdateLabel(Hostname, HostnameLabel);
}
private void UpdateLabel(TextBox textBox, Label label)
{
label.Visibility = String.IsNullOrWhiteSpace(textBox.Text) ? Visibility.Visible : Visibility.Hidden;
}
This works for password boxes too, which are sealed, so you cannot inherit them anyways if you tried to extend sealed controls.

How do I remove the X axis labels from this chart?

Keeping myself concise and to the point I wish to remove the labels or at the very least modify them from my X-Axis :
I seem to be using a modified version of this library that allows me to use some tools usually won't work in wp7.
xmlns:charting="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit"
This is the LineSeries definitions as of right now :
<charting:Chart x:Name="chart" Title="Humidity Readings" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Foreground="#FF3C58C8">
<chartingToolkit:LineSeries x:Name="HumidityGraph" Title="Humidity" BorderThickness="2" ItemsSource="{Binding Data}" IndependentValuePath="Time" DependentValuePath="Measurement"/>
</charting:Chart>
In response to chridam I tried implementing his suggestion - No succes.
<charting:Chart x:Name="chart" Title="Humidity Readings" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Foreground="#FF3C58C8">
<charting:Chart.LegendStyle>
<Style TargetType="visualizationToolkit:Legend">
<Setter Property="Width" Value="0"/>
<Setter Property="Height" Value="0"/>
</Style>
</charting:Chart.LegendStyle>
<!--there doesn't seem to be an AxisLabelStyle that I can create a style in.-->
<Style x:Key="EmptyStyle" TargetType="charting:NumericAxisLabel">
<Setter Property="StringFormat" Value="" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="charting:NumericAxisLabel">
<TextBlock />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<chartingToolkit:LineSeries x:Name="HumidityGraph" Title="Humidity" BorderThickness="2" ItemsSource="{Binding Data}" IndependentValuePath="Time" DependentValuePath="Measurement" TransitionDuration="0:1:1.5" FontSize="18.667">
<charting:LinearAxis AxisLabelStyle="{StaticResource EmptyStyle}" Orientation="X" ShowGridLines="True"/>
</chartingToolkit:LineSeries>
</charting:Chart>
Try specifying a style for Axis Label that sets the StringFormat property value to empty
<chartingToolkit:CategoryAxis>
<chartingToolkit:CategoryAxis.AxisLabelStyle>
<Style TargetType="AxisLabel">
<Setter Property="StringFormat" Value=""></Setter>
</Style>
</chartingToolkit:CategoryAxis.AxisLabelStyle>
</chartingToolkit:CategoryAxis>
Update:
Another alternative is to apply the style template
<Style x:Key="EmptyStyle" TargetType="charting:NumericAxisLabel">
<Setter Property="StringFormat" Value="" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="charting:NumericAxisLabel">
<TextBlock />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
to this:
<charting:LineSeries.DependentRangeAxis>
<charting:LinearAxis AxisLabelStyle="{StaticResource EmptyStyle}"
Orientation="X"
ShowGridLines="True"/>
</charting:LineSeries.DependentRangeAxis>
For more resources on styling the chart, Styling a Silverlight Chart

Categories

Resources