I would like to build a validation text box, which would be a normal UWP TextBox wrapped within a StackPanel, which also contains a TextBlock. The intent is that a validation message can be shown beneath the text box when there is a validation error.
I know I can do this by creating a custom control, but this would require me to implement all the properties I need and create a bunch of dependency properties, etc.
I'm hoping there is an easier way, where I can just completely derive the text box, but override the display template for it and include a label beneath it.
You can get most of the way there in XAML using the built-in IDataErrorInfo-based validation machinery and defining a control template for the TextBox's Validation.ErrorTemplate. There's a pretty good article at this link:
The XAML from the article at the link above follows, also check out this discussion on WPF's built-in validation here.
<Style TargetType="{x:Type Label}">
<Setter Property="Margin" Value="5,0,5,0" />
<Setter Property="HorizontalAlignment" Value="Left" />
</Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="0,2,40,2" />
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="true">
<Border Background="OrangeRed" DockPanel.Dock="right" Margin="5,0,0,0"
Width="20" Height="20" CornerRadius="5"
ToolTip="{Binding ElementName=customAdorner,
Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
<TextBlock Text="!" VerticalAlignment="center" HorizontalAlignment="center"
FontWeight="Bold" Foreground="white" />
</Border>
<AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
<Border BorderBrush="red" BorderThickness="1" />
</AdornedElementPlaceholder>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
In this post, I want to use a same solution to do with button. But I want to store the content to an other resource.(I mean XamlImage in below sample) What is the type for content of button to store xaml data in resource dictionary?
Below is sample from the post. I added XamlImage as path in resource but it doesn't work. So, what type should it be?
<Path x:Key="XamlImage" Data="M383.518,230.427C299.063,230.427 230.355,299.099 230.355,383.554 230.355,468.009 299.063,536.644 383.518,536.644 467.937,536.644 536.645,468.009 536.645,383.554 536.645,299.099 467.937,230.427 383.518,230.427z M340.229,0L426.771,0C436.838,0,445.035,8.19732,445.035,18.2643L445.035,115.303C475.165,122.17,503.532,133.928,529.634,150.43L598.306,81.6869C601.721,78.3074 606.359,76.3653 611.213,76.3653 616.031,76.3653 620.704,78.3074 624.12,81.6869L685.278,142.916C692.397,150.035,692.397,161.648,685.278,168.767L616.677,237.402C633.108,263.54,644.866,291.907,651.733,322.001L748.736,322.001C758.803,322.001,767,330.198,767,340.265L767,426.806C767,436.873,758.803,445.07,748.736,445.07L651.769,445.07C644.901,475.235,633.108,503.531,616.677,529.669L685.278,598.305C688.694,601.72 690.635,606.358 690.635,611.212 690.635,616.102 688.694,620.705 685.278,624.12L624.085,685.313C620.525,688.872 615.851,690.67 611.177,690.67 606.503,690.67 601.865,688.872 598.269,685.313L529.67,616.678C503.567,633.109,475.2,644.937,445.035,651.804L445.035,748.771C445.035,758.838,436.838,767,426.771,767L340.229,767C330.162,767,321.965,758.838,321.965,748.771L321.965,651.804C291.8,644.937,263.433,633.109,237.366,616.678L168.731,685.313C165.315,688.693 160.677,690.67 155.823,690.67 151.005,690.67 146.296,688.693 142.916,685.313L81.7221,624.12C74.6033,617.036,74.6033,605.424,81.7221,598.305L150.323,529.669C133.892,503.603,122.099,475.235,115.267,445.07L18.2643,445.07C8.19734,445.07,0,436.873,0,426.806L0,340.265C0,330.198,8.19734,322.001,18.2643,322.001L115.267,322.001C122.135,291.907,133.892,263.54,150.323,237.402L81.7221,168.767C78.3064,165.351 76.3655,160.713 76.3655,155.859 76.3655,150.97 78.3064,146.332 81.7221,142.916L142.916,81.7582C146.476,78.1988 151.149,76.4016 155.823,76.4016 160.497,76.4016 165.171,78.1988 168.731,81.7582L237.366,150.43C263.469,133.928,291.837,122.17,321.965,115.303L321.965,18.2643C321.965,8.19732,330.162,0,340.229,0z"/>
<Style x:Key="PathAppBarButtonStyle" BasedOn="{StaticResource AppBarButtonStyle}" TargetType="ButtonBase">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Path Width="20" Height="20"
Stretch="Uniform"
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Data="{Binding Path=Content, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
</DataTemplate>
</Setter.Value>
</Setter>
<Style x:Key="CrossButtonStyle" TargetType="ButtonBase" BasedOn="{StaticResource PathAppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="CrossAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Cross"/>
<Setter Property="Content" Value="{StaticResource XamlImage}"/>
</Style>
You don't want to set an image resource as your content because Image is a control and it can only be in one place in your UI tree. You can reuse a DataTemplate though in your ContentTemplate. So just put an Image inside of that.
In a Windows 8 (WinRT) app, I am creating my own XAML style to get a dotted rectangle. In the setter for the style, I use Property="StrokeDashArray" Value="1,4". I then create a bunch of rectangles, and then explicitly set the style of those rectangles to this style I created. The first rectangle shows up with a dotted border - but the other two don't. However, if in addition to the Style={StaticResource myDottedStyle} I also specify the StrokeDashArray with each rectangle, then all them correctly show up with dotted borders.
Why is the dotted border only showing up for the first rectangle? How can I create a Style that is applied to all the rectangles without specifying the StrokeDashArray for each of them?
Here is a full code sample. In Windows 8 RTM, create a Blank XAML app project, and replace the Grid in the MainPage.xaml with the following:
<Page.Resources>
<Style x:Key="myDottedStyle" TargetType="Rectangle">
<Setter Property="Stroke"
Value="{StaticResource ApplicationForegroundThemeBrush}"/>
<Setter Property="StrokeThickness" Value="2"/>
<Setter Property="StrokeDashArray" Value="1,4"/>
</Style>
</Page.Resources>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Rectangle Style="{StaticResource myDottedStyle}" Width="40"
HorizontalAlignment="Left"/>
<Rectangle Style="{StaticResource myDottedStyle}" Width="40"
HorizontalAlignment="Center"/>
<Rectangle Style="{StaticResource myDottedStyle}" Width="40"
HorizontalAlignment="Right"/>
</Grid>
Here is a screenshot of the output of this
I found a related question that talks about DataTemplates here but I can't figure out how to translate that into my problem.
You could optimize things a bit by not requiring it to re-draw the rectangle per each instance and substitute for a ContentControl instead since they appear the same but with minor differences. So something for example like;
<Style x:Key="MyDottedStyle" TargetType="ContentControl">
<!-- Add additional Setters Here -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Rectangle Stroke="{StaticResource ApplicationForegroundThemeBrush}"
StrokeThickness="2"
StrokeDashArray="1,4"
Width="40" Height="40"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
Margin="{TemplateBinding Margin}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- And now actually place it on your view -->
<ContentControl Style="{StaticResource MyDottedStyle}" HorizontalAlignment="Center"/>
This will allow you to not only clean things up because you can take your Style template and slap it over into say a Resource Dictionary to reduce clutter, but also makes it a little more efficient since you're not re-drawing your shape every time it's required. Hope this helps! Cheers!
I created a Silverlight Column chart and rotated the X-Axis, following the guidelines of this MSDN Blog. The labels are rotated correctly, but I end up with staggered labels in my X-Axis, which does not fit well. I would like to remove the stagger from the labels.
Here is the XAML:
<toolkit:Chart Name="theColumnChart" BorderThickness="0" Margin="5"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Style="{StaticResource Chart}"
Template="{StaticResource ChartTemplate}" TitleStyle="{StaticResource ChartTitleStyle}">
<toolkit:Chart.Palette>
<visualizationToolkit:ResourceDictionaryCollection>
<ResourceDictionary>
<Style x:Key="DataPointStyle" TargetType="toolkit:ColumnDataPoint" BasedOn="{StaticResource ColumnDataPointStyle}">
<Setter Property="Background" Value="Goldenrod"/>
</Style>
</ResourceDictionary>
<ResourceDictionary>
<Style x:Key="DataPointStyle" TargetType="toolkit:ColumnDataPoint" BasedOn="{StaticResource ColumnDataPointStyle}">
<Setter Property="Background" Value="SaddleBrown"/>
</Style>
</ResourceDictionary>
</visualizationToolkit:ResourceDictionaryCollection>
</toolkit:Chart.Palette>
<toolkit:Chart.Axes>
<toolkit:LinearAxis Minimum="0" Orientation="Y" />
</toolkit:Chart.Axes>
<toolkit:Chart.Series>
<toolkit:ColumnSeries DependentValueBinding="{Binding ItemValue}" IndependentValueBinding="{Binding ItemKey}"
ItemsSource="{Binding Statistics1}" Title="{Binding SeriesTitle}">
<toolkit:ColumnSeries.IndependentAxis>
<toolkit:CategoryAxis Orientation="X">
<toolkit:CategoryAxis.AxisLabelStyle>
<Style TargetType="toolkit:AxisLabel">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="toolkit:AxisLabel">
<layout:LayoutTransformer>
<layout:LayoutTransformer.LayoutTransform>
<RotateTransform Angle="-45"/>
</layout:LayoutTransformer.LayoutTransform>
<TextBlock Text="{TemplateBinding FormattedContent}"/>
</layout:LayoutTransformer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</toolkit:CategoryAxis.AxisLabelStyle>
</toolkit:CategoryAxis>
</toolkit:ColumnSeries.IndependentAxis>
</toolkit:ColumnSeries>
</toolkit:Chart.Series>
</toolkit:Chart>
Here is a picture of the problem:
When the labels are rotated by 90°, even with visually sufficient space between them, the stagger occurs, not sure why. So I end up with vertical staggered labels with plenty of space between them!
I came across the problem today, and I found a slightly hacky solution which does not require the modification of the control itself, but only involves a custom control template.
The following code shows the date labels vertically, and remove the stagger.
Every label is wrapped into a Canvas, which, as explained here, does not clip its content.
I had to modify the labels' margins to align them with axis marks.
<toolkit:DateTimeAxis.AxisLabelStyle>
<Style TargetType="toolkit:DateTimeAxisLabel">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="toolkit:DateTimeAxisLabel">
<Canvas Height="55">
<sdk:Label Content="{Binding StringFormat=\{0:dd/MM/yyyy\}}" Margin="-30,30,0,0" >
<sdk:Label.RenderTransform>
<RotateTransform Angle="-90" />
</sdk:Label.RenderTransform>
<sdk:Label.RenderTransformOrigin>
<Point>0.5, 0.5</Point>
</sdk:Label.RenderTransformOrigin>
</sdk:Label>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</toolkit:DateTimeAxis.AxisLabelStyle>
here is the result:
Rachel Martin,
The labels above are still wide enough that there's not enough room to fit them all next to each other. You could choose to rotate the text more (which will narrow each label) or make the chart wider (which will provide more room for the labels). If you don't like either of those options, you can also remove the stagger behavior, but it's necessary to modify the Data Visualization code to do so; I explain how here: http://blogs.msdn.com/b/delay/archive/2010/03/06/turn-your-head-and-check-out-this-post-how-to-easily-rotate-the-axis-labels-of-a-silverlight-wpf-toolkit-chart.aspx#10083036
Hope this helps!