WPF Can't Remove Red Border from UserControl - wpf

I've built a simple login page and when invalid input is detected, a red border is drawn around the usercontrol.
Here is my layout code:
<UserControl x:Class="WPFTest.UI.Views.EmptyLayout"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WPFTest.UI.Views"
xmlns:vm="clr-namespace:WPFTest.UI.ViewModels"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance Type=vm:EmptyLayoutViewModel}"
Background="White"
>
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" FontSize="20" FontWeight="Bold">Test Sales Estimator</TextBlock>
<ContentControl Content="{Binding Layout}" Grid.Row="1">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type vm:LoginViewModel}">
<local:LoginView/>
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
</Grid>
</UserControl>
And here is the login view:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WPFTest.UI.Views" xmlns:viewmodels="clr-namespace:WPFTest.UI.ViewModels"
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls" x:Class="WPFTest.UI.Views.LoginView"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Background="White"
d:DataContext="{d:DesignInstance Type={x:Type viewmodels:LoginViewModel}}"
Margin="20 0 0 0"
Padding="10"
>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="2" Margin="0 50 0 0">
<TextBlock Text="Welcome" FontSize="17" Grid.Row="1" Margin="0 0 0 20" Height="50"/>
<StackPanel>
<TextBlock Text="Username" />
<TextBox Text="{Binding Username}"/>
</StackPanel>
<StackPanel Grid.Row="2" Margin="0 10 0 0">
<TextBlock Text="Password" />
<PasswordBox x:Name="Password" PasswordChanged="PasswordBox_PasswordChanged" >
</PasswordBox>
</StackPanel>
<Button
Grid.Row="2"
Margin="0 20 0 0"
Padding="5 2"
HorizontalAlignment="Left"
Command="{Binding HandleLoginCommand}"
IsEnabled="{Binding CanLogin}"
Content="Login">
</Button>
</StackPanel>
</Grid>
</UserControl>
I have tried to override the border with the following template:
<Style TargetType="views:LoginView">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="BorderBrush" Value="Blue"/>
<Setter Property="BorderThickness" Value="1"/>
</Trigger>
</Style.Triggers>
</Style>
But the border remains red. I've also tried changing the target on the template to things like UserControl, and ContentControl. I've also tried setting the Validation.ErrorTemplate attribute to {x:Null} on both the UserControl and on the element inside the layout usercontrol.
For the LoginViewModel, I am using the CommunityToolkit.Mvvm's ObservableValidator as my base class, so it handles the validation logic and here is my Username property.
private string _username;
[Required]
[MinLength(4)]
public string Username
{
get { return _username; }
set {
SetProperty(ref _username, value, true);
OnPropertyChanged(nameof(HandleLoginCommand));
}
}

The border is from your contentcontrol.
Set Validation.ErrorTemplate="{x:Null}" on that.
You can just use a contentpresenter.
<ContentPresenter Content="{Binding Layout}" Grid.Row="1"
Validation.ErrorTemplate="{x:Null}">
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type local:LoginViewModel}">
<local:LoginView/>
</DataTemplate>
</ContentPresenter.Resources>
</ContentPresenter>
I have a simplified layout to explore this, but the outer red border does not appear when I make that change.

The validation decoration does not use the control's Border(Thcikness/Brush). It is instead a separate Visual that is drawn in a separate AdornerLayer. To modify its looks, you should pass a dedicated template for the ErrorTemplate like this: (example for TextBox)
<Style TargetType="TextBox">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<Grid>
<Border BorderBrush="Yellow" BorderThickness="3">
<AdornedElementPlaceholder x:Name="AdornedElementPlaceholder" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
To actually remove the border, try setting Validation.ErrorTemplate to {x:Null}.

Related

Overriding Style of WPF TreeView Items

I am using the awesome MahAppsMetro WPF control suite. I have a tree view that loads the file system. I also want to display images in the TreeViewItems so I have overridden the metro tree style as follows
<UserControl x:Class="GDE.Tree.TreeView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:Caliburn="http://www.caliburnproject.org"
xmlns:Metro="http://metro.mahapps.com/winfx/xaml/controls"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300">
<UserControl.Resources>
<HierarchicalDataTemplate x:Key="TreeTemplate" ItemsSource="{Binding Path=Children}"/>
</UserControl.Resources>
<!--TreeView-->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox Grid.Row="0"
Margin="5"
IsReadOnly="True"
Text="{Binding SelectedPath, Mode=TwoWay}"/>
<TreeView Grid.Row="1"
Margin="5"
ItemsSource="{Binding RootChildren}"
ItemTemplate="{StaticResource TreeTemplate}">
<TreeView.Resources>
<Style TargetType="{x:Type TreeViewItem}"
BasedOn="{StaticResource MetroTreeViewItem}">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Name="img"
Width="16"
Height="16"
Stretch="Fill"
Source="{Binding Path=Icon, Mode=OneTime}"
VerticalAlignment="Center"
HorizontalAlignment="Center"/>
<TextBlock Text="{Binding DisplayName, Mode=OneTime}"
Margin="5,0,0,0"
VerticalAlignment="Center"
HorizontalAlignment="Left"/>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TreeView.Resources>
</TreeView>
</Grid>
</UserControl>
But this does not seem to work as intended and I can't figure out why. From this XAML, I get no binding errors and the visuals look like:
I have gone more extensive with the XAML mark up but I am getting the exact same visuals. How can I change the above XAML to give me the Image/TextBlocks as well as the MahApps look and feel?
Thanks for your time.
To sum up comments instead of changing Style you need to move StackPanel from DataTemplate directly into HierarchicalDataTemplate as at the moment used template has no content:
<HierarchicalDataTemplate x:Key="TreeTemplate" ItemsSource="{Binding Path=Children}">
<StackPanel Orientation="Horizontal">
<Image Name="img" ... />
<TextBlock Text="{Binding DisplayName, Mode=OneTime}" ... />
</StackPanel>
</HierarchicalDataTemplate>

Issue templating RadioButton in Silverlight 5

I try to apply a really simple ControlTemplate to a RadioButton. But that cause in a weird behavior.
As Long as I´m just clicking the Label everything works fine, but when I click the button control itself it never changes again. Here the complete code of the control:
<UserControl x:Class="RadioButtonDemo.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.Resources>
<ControlTemplate TargetType="RadioButton" x:Key="RadioButtonTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{TemplateBinding Content}"/>
<RadioButton IsChecked="{TemplateBinding IsChecked}" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
<Style TargetType="RadioButton" x:Key="RadioButtonStyle">
<Setter Property="Template" Value="{StaticResource RadioButtonTemplate}"/>
</Style>
</UserControl.Resources>
<StackPanel>
<RadioButton Content="Textbox diabled" GroupName="Group1" Style="{StaticResource RadioButtonStyle}"/>
<RadioButton x:Name="EnabledButton" Content="Textbox enabled" GroupName="Group1" Style="{StaticResource RadioButtonStyle}"/>
<TextBox IsEnabled="{Binding IsChecked, ElementName=EnabledButton}"/>
</StackPanel>
Can someone help?
Please get default style from following link,
http://msdn.microsoft.com/en-us/library/cc296247(v=vs.95).aspx
Use the template by just swapping content and button(:-( code is bulk).

Binding to the UserControl Inside HierarchicalDataTemplate in Silverlight

I have customized TreeView in usercontrol.
In the HierarchicalDataTemplate I have an image with direction (arrow for the example).
When the application\UserControl flow direction change I need to flip the image.
So i tried binding the Image.FlowDirection (Which is flipping the image automatic when RightToLeft) to the UserControl.FlowDirection
<Image FlowDirection="{Binding Path=FlowDirection,
ElementName=MyUserControl}" ... />
But it is not working. I guess because he can't find the UserControl from inside the template.
I've tried this binding outside the template - and it's working fine.
Any solution ?
How can I get my UserControl from inside the template ?
--UPDATE--
There are two places of binding in this xaml. The first is in the style of the button, and it is working, and the second in the template of the TreeViewItem - and there it's not working.
<UserControl x:Class="MyTree"
...
d:DesignHeight="218" d:DesignWidth="284" x:Name="MyLayerListControl">
<UserControl.Resources>
<Style x:Key="CloseButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
...
</VisualStateManager.VisualStateGroups>
<Border x:Name="CloseButtonBorder" BorderThickness="0" Margin="3" CornerRadius="0" Background="Gray" >
<!-- THIS BINDING IS WORKING -->
<Image Source="{StaticResource back}" Margin="2"
FlowDirection="{Binding Path=FlowDirection, ElementName=MyLayerListControl}"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="Transparent">
<Button Style="{StaticResource CloseButtonStyle}" />
<Grid>
<Grid.ColumnDefinitions></Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.Resources>
<sdk:HierarchicalDataTemplate x:Key="LayerListTemplate" ItemsSource="{Binding Path=Childrens}" >
<Grid>
<Border CornerRadius="2" BorderBrush="#FF6DBDD1" BorderThickness="1" Background="#FFBADDE9" Opacity="0.5" />
<StackPanel Orientation="Vertical">
<!-- The Item -->
<StackPanel Orientation="Horizontal" Margin="3">
<!-- THIS BINDING IS NOT WORKING -->
<Image x:Name="ArrowImage" Width="16" Height="16" Source="{StaticResource arrow}"
FlowDirection="{Binding Path=FlowDirection, ElementName=MyLayerListControl}"/>
</StackPanel>
</StackPanel>
</Grid>
</sdk:HierarchicalDataTemplate>
</Grid.Resources>
<sdk:TreeView ItemsSource="{Binding}" ItemTemplate="{StaticResource LayerListTemplate}" x:Name="MyTreeView" Grid.Row="1" />
</Grid>
</Grid>
</UserControl>
As #Chris says, add "DataContext" in front of you binding path, as you are binding to the Control itself, so if FlowDirection is a property of the DataContext, you need to have that.
Also, make sure you have Mode=TwoWay in your binding.
As an alternative, you can you use RelativeSource so you don't have to hard code an ElementName.
Check out: http://tonychampion.net/blog/index.php/2011/12/7th-day-of-silverlight-ancestor-relative-source-binding/

Trouble with setting both DataTemplate and ControlTemplate to Map Pushpins in WPF

I am having trouble setting both DataTemplate and ControlTemplate to my bing map pushpins. I am using data binding which works to a point when i try to customize my pushpins by adding ControlTemplate.
My code:
<UserControl x:Class="BingMap.MapUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:m="clr-namespace:Microsoft.Maps.MapControl.WPF;assembly=Microsoft.Maps.MapControl.WPF"
xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing"
xmlns:viewPushpins="clr-namespace:Program.Map_Control.ViewPushpins">
<UserControl.DataContext>
<viewPushpins:MapViewPushpins/>
</UserControl.DataContext>
<UserControl.Resources>
<DataTemplate x:Key="PushpinDataTemplateP">
<m:Pushpin Location = "{Binding MapLocationP}" ToolTip="{Binding MapTooltipTextP}"/>
</DataTemplate>
<ControlTemplate x:Key="PushpinControlTemplateP">
<Grid>
<Ellipse Fill="Green" Width="15" Height="15" />
</Grid>
</ControlTemplate>
</UserControl.Resources>
<Grid>
<m:Map Name="myMap"
CredentialsProvider="..."
ZoomLevel="1"
Center="30,-100"
Mode="AerialWithLabels"
MouseLeftButtonUp="Map_Left_Click_Up">
<m:MapItemsControl
Template="{StaticResource PushpinControlTemplateP}"
ItemTemplate="{StaticResource PushpinDataTemplateP}" MouseLeftButtonUp="Map_Left_Click_Up"
ItemsSource="{Binding MapLocationsP}"/>
</m:Map>
</Grid>
</UserControl>
This code works if I remove the line:
Template="{StaticResource PushpinControlTemplateP}"
but then don't get my customized pushpin.
Any ideas on how can I fix this?
By setting MapItemsControl.Template, you're specifying a template for the MapItemsControl itself, not the items it produces. You can set the template for individual items produced by an ItemsControl indirectly via the ItemContainerStyle:
<Style x:Key="PushPinStyle">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<!-- your template goes here -->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<m:MapItemsControl ItemContainerStyle="{StaticResource }" ...>
I see where i got this wrong. As already mentioned by Kent, the line
Template="{StaticResource PushpinControlTemplateP}"
shouldn't be in MapItemsControl.
I solved my problem with moving this line of code to Resources so they look like this:
<UserControl.Resources>
<ControlTemplate x:Key="PushpinControlTemplateP">
<Grid>
<Ellipse Fill="Green" Width="15" Height="15" />
</Grid>
</ControlTemplate>
<DataTemplate x:Key="PushpinDataTemplateP">
<m:Pushpin Location = "{Binding MapLocationP}" ToolTip="{Binding MapTooltipTextP}" Template="{StaticResource PushpinControlTemplateP}"/>
</DataTemplate>
</UserControl.Resources>

WPF- Validation -The validation error message goes behind the other controls because of AdornerDecorator

I have implemented IDataErrorInfo in my ViewModel to return a string if the text box has error.
public string this[string columnName]
{
get { return "Error-- This is a long error message - sd"; }
}
But this error message goes behind the other control on the UI as shown below.
Below is the xaml:
<Window x:Class="Test.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="600" Width="600">
<Window.Resources>
<ControlTemplate x:Key="validationTemplateNew">
<DockPanel LastChildFill="True">
<TextBlock Name="ErrorText" DockPanel.Dock="Bottom" Foreground="White" Background="Red"
FontSize="12" Padding="2" FontFamily="Trebuchet MS"
Margin="5,5,0,0"
TextWrapping="Wrap"
Text="{Binding [0].ErrorContent}" ></TextBlock>
<AdornedElementPlaceholder Name="ErrorTextBox" />
</DockPanel>
</ControlTemplate>
<Style x:Key="ValidationStyle" TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="BitmapEffect">
<Setter.Value>
<BitmapEffectGroup>
<OuterGlowBitmapEffect GlowColor="Red" GlowSize="3" Noise="0.6"></OuterGlowBitmapEffect>
</BitmapEffectGroup>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<ItemsControl Name="ItemCtrl">
<AdornerDecorator>
<TextBox
FontSize="11"
Margin="10"
Width="250"
VerticalAlignment="Center"
Text="{Binding Path=StrText, ValidatesOnDataErrors=True,
UpdateSourceTrigger=PropertyChanged}"
Validation.ErrorTemplate="{StaticResource validationTemplateNew}"
Style="{StaticResource ValidationStyle}"
>
</TextBox>
</AdornerDecorator>
<TextBox Width="250" Text="ASDFASFASDFASDFASDFASDFASDF"/>
<TextBox Width="250" Text="ASDFASFASDFASDFASDFASDFASDF"/>
<TextBox Width="250" Text="ASDFASFASDFASDFASDFASDFASDF"/>
<TextBox Width="250" Text="ASDFASFASDFASDFASDFASDFASDF"/>
<TextBox Width="250" Text="ASDFASFASDFASDFASDFASDFASDF"/>
</ItemsControl>
</Grid>
</Window>
Please let me know how to use AdornerDecorator such that the error message overlaps the other controls and doesn't go behind.
My application is such that if I don't use AdornerDecorator, the error message is not displayed at all.
Adding Grid.ZIndex on the AdornerDecorator should be enough
<Grid>
<ItemsControl Name="ItemCtrl">
<AdornerDecorator Grid.ZIndex="1">

Resources