Custom control with text box and text block - xaml

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>

Related

How to change ComboBox placeholder foreground in UWP

I would like to change ComboBox placeholder color in my demo UWP app. So I tried to create static resources:
<UserControl.Resources>
<Style x:Key="ComboBoxStyle" TargetType="ComboBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBox">
<ContentControl x:Name="PlaceholderTextContentPresenter"
Content="{TemplateBinding PlaceholderText}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
Using:
<ComboBox Grid.Row="1" Foreground="White" HorizontalAlignment="Stretch" Background="Transparent"
PlaceholderText="Выбор оператора" Style="{StaticResource ComboBoxStyle}">
<x:String>iPhone 11</x:String>
<x:String>iPhone 12</x:String>
<x:String>Xiaomi Red Mi</x:String>
<x:String>Samsung Galaxy 10</x:String>
<ComboBox.Resources>
<Style TargetType="ContentControl">
<Setter Property="Foreground" Value="White" />
<Setter Property="FontSize" Value="15" />
</Style>
</ComboBox.Resources>
</ComboBox>
Foreground in placeholder changed correctly but ComboBox is disappeared. How can I will change ComboBox placeholder foreground?
How to change ComboBox placeholder foreground in UWP
UWP ComboBox contains PlaceholderForeground propety, if you want to chage the default one, you just need to give it specific value like the following. And please not the property avaiable in version 16299 or higher.
<ComboBox
Grid.Row="1"
HorizontalAlignment="Stretch"
Background="Transparent"
Foreground="White"
PlaceholderText="Выбор оператора"
PlaceholderForeground="DarkBlue">
<x:String>iPhone 11</x:String>
<x:String>iPhone 12</x:String>
<x:String>Xiaomi Red Mi</x:String>
<x:String>Samsung Galaxy 10</x:String>
</ComboBox>

Central margin definition for a button with Materialdesigninxaml style

I have a quick (and most likely) easy question for which I unfortunately do not find a suitable solution. My requirements are as follows:
For the purpose of creating a navigation bar, I want to stack some buttons. For this purpose, I am using a stack panel.
Between each of the buttons, I want to have some space. I could of course set the margin for every button, however I find this solution not very robust and instead want to define the margin centrally.
What I therefore did is I defined a style within the stack panel and set the margin once. This works great with one issue: For the button I would love to use a style provided by Materialdesigninxaml. When I however set the style to the button, the margin style gets ignored.
Has anyone an idea or do I need to make use of a workaround?
Thank you guys for your help.
Here is my sample code which works as no Materialdesigninxaml style is defined:
<StackPanel.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Margin" Value="0 10 0 0"/>
<Setter Property="Height" Value="50"/>
<Setter Property="Width" Value="150"/>
</Style>
</StackPanel.Resources>
<Button>
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="Database" VerticalAlignment="Center"/>
<TextBlock Text="BUTTON 1"/>
</StackPanel>
</Button>
This is my code with a specified Materialdesigninxaml style which does not work:
<StackPanel.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Margin" Value="0 10 0 0"/>
<Setter Property="Height" Value="50"/>
<Setter Property="Width" Value="150"/>
</Style>
</StackPanel.Resources>
<Button Style="{DynamicResource MaterialDesignFlatButton}">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="Database" VerticalAlignment="Center"/>
<TextBlock Text="BUTTON 1"/>
</StackPanel>
</Button>

What is the type for content of button to store xaml data in resource?

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.

How to set and get line series color from WinRT XAML Toolkit chart

ANSWER
Thanks Filip, finally I found way to set the color. I just need to add Background property in DataPointStyle. I am posting my answer here. Also found a way how to modify the default tooltip.
Showing lines with different colors on a Silverlight Toolkit’s LineChart?
Using a custom ToolTip in Silverlight charting
<charting:LineSeries.DataPointStyle>
<Style TargetType="charting:LineDataPoint">
<Setter Property="Width" Value="17" />
<Setter Property="Height" Value="17" />
<Setter Property="Background" Value="Lime"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="charting:LineDataPoint">
<Grid>
<ToolTipService.ToolTip>
<ContentControl Content="{Binding Value,Converter={StaticResource MyConv},ConverterParameter=TEST}"/>
</ToolTipService.ToolTip>
<Ellipse Fill="Lime" Stroke="Lime" StrokeThickness="3" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</charting:LineSeries.DataPointStyle>
Question 1
I am creating multiple line chart series in a chart. Now WinRT XAML Toolkit assigns color for each series in random manner. I am using custom style for data points, so when I use custom style that randomness of color goes off. So how can I set or get that random color of series ? If I can get the color then I can use that color in datapoint, and if I can set color then I will generate random color myself.
Question 2
Moreover while hovering over data points the tool tip shows the dependent value, but I want to show more details how can I achieve that ?
Here's my code with custom style.
<charting:Chart x:Name="LineChart" Title="Line Chart" Margin="70,0">
<charting:LineSeries
Title="Population 1"
IndependentValueBinding="{Binding Name}"
DependentValueBinding="{Binding Value}"
IsSelectionEnabled="True">
<charting:LineSeries.DataPointStyle>
<Style TargetType="charting:LineDataPoint">
<Setter Property="Width" Value="17" />
<Setter Property="Height" Value="17" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="charting:LineDataPoint">
<Ellipse Fill="Green" Stroke="Green" StrokeThickness="3" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</charting:LineSeries.DataPointStyle>
</charting:LineSeries>
<charting:LineSeries
Title="Population 2"
IndependentValueBinding="{Binding Name}"
DependentValueBinding="{Binding Value}"
IsSelectionEnabled="True" Foreground="Blue">
<charting:LineSeries.DataPointStyle>
<Style TargetType="charting:LineDataPoint">
<Setter Property="Width" Value="17" />
<Setter Property="Height" Value="17" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="charting:LineDataPoint">
<Ellipse Fill="Red" Stroke="Red" StrokeThickness="3" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</charting:LineSeries.DataPointStyle>
</charting:LineSeries>
</charting:Chart>
Chart with random color (NO CUSTOM DATAPOINT STYLE)
Chart with NO random color (WITH CUSTOM DATAPOINT STYLE) [You can see both line has yellow color]
Trying to Bing for silverlight toolkit chart custom line color yields some potentially useful pages, like this. It should work mostly the same with the WinRT XAML Toolkit, but where they customize the Silverlight-based templates - you would need to customize the WinRT XAML Toolkit-based ones that you can either try to extract with Blend/Visual Studio designer or get the original templates from the source that you can grab from CodePlex.

Gridview items as squares in WinRT (metro)

I've been struggeling with this a few days now and can't get it to work.
Maybe I'm not as good XAML programmer that I hoped I would be :)
Anyhow, my problem is that i want to bind a number of elements to a GridView and make them appear as squares without setting any width and height. The reason for this is that I want my GridView items to grow/shrink and expand to maximum size as the resolution or screen size vary.
Here is my XAML:
<UserControl.Resources>
<Style x:Key="MyItemContainerStyle" TargetType="ListViewItem">
<Setter Property="FontFamily" Value="Segoe UI" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<!--<Setter Property="Height" Value="{Binding RelativeSource={RelativeSource Self}, Path=Width}" />-->
</Style>
<DataTemplate x:Key="MyItemTemplate">
<Border CornerRadius="4"
BorderBrush="Black"
BorderThickness="1"
Background="Blue">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center">X</TextBlock>
</Border>
</DataTemplate>
<ItemsPanelTemplate x:Key="MyItemsPanelTemplate">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center" />
</ItemsPanelTemplate>
</UserControl.Resources>
<Grid Background="White">
<GridView x:Name="MyGrid"
UseLayoutRounding="True"
ItemTemplate="{StaticResource MyItemTemplate}"
ItemsPanel="{StaticResource MyItemsPanelTemplate}"
ItemContainerStyle="{StaticResource MyItemContainerStyle}"
ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto">
</GridView>
</Grid>
And this is my code-behind:
public sealed partial class BlankPage : Page
{
public BlankPage()
{
this.InitializeComponent();
MyGrid.Items.Add(new ListViewItem { Content = 1 });
MyGrid.Items.Add(new ListViewItem { Content = 2 });
MyGrid.Items.Add(new ListViewItem { Content = 3 });
}
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached. The Parameter
/// property is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
}
This however produces an output like this (rectangular items, not squares):
I would appreciate if someone who knows a bit more about XAML and WinRT (metro) development than I do, could explain this for me and maybe give me a working example.
Thanx!
EDIT
I got a tip to wrap my Border in a Viewbox as it seems to have some scaling/stretching abilities.
I played around a couple of hours but I can't really get it to work 100%.
This is my XAML now:
<UserControl.Resources>
<Style x:Key="MyItemContainerStyle" TargetType="ListViewItem">
<Setter Property="FontFamily" Value="Segoe UI" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
</Style>
<DataTemplate x:Key="MyItemTemplate">
<Viewbox>
<Border CornerRadius="3"
BorderBrush="Black"
BorderThickness="1">
<Grid Background="Blue" MinHeight="50" MinWidth="50">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center">X</TextBlock>
</Grid>
</Border>
</Viewbox>
</DataTemplate>
<ItemsPanelTemplate x:Key="MyItemsPanelTemplate">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
</StackPanel>
</ItemsPanelTemplate>
</UserControl.Resources>
<Grid Background="White">
<GridView x:Name="MyGrid"
UseLayoutRounding="True"
ItemTemplate="{StaticResource MyItemTemplate}"
ItemsPanel="{StaticResource MyItemsPanelTemplate}"
ItemContainerStyle="{StaticResource MyItemContainerStyle}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Disabled">
</GridView>
</Grid>
This produces this output:
Now it seems to stretch itself to a sqaure, but it sretches itself outside the screen. I also ran this example in several resoultions and screen sizes and it shows the same output, which means it scales correctly.
Help would be appreciated.
Thanx!
Your commented out binding is close to something that could sort of work - only you would need to bind to ActualWidth:
<Setter Property="Height" Value="{Binding ActualWidth, RelativeSource={RelativeSource Self}}" />
Overall I would suggest using hardcoded values - they make things easier on the CPU to layout, easier to deterministically design and will get scaled by Windows when screen size and resolution will require that. If you want more control over that - you can bind both Width and Height to the same value from a view model that you change depending on the need or write a converter that will convert a hardcoded Width/Height value to actual value depending on detected screen size/resolution or settings.