Skip to content

Commit 0e1c031

Browse files
committed
Add validationerrortemplate and validationassist
1 parent c9eb411 commit 0e1c031

8 files changed

+209
-14
lines changed
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using System.Windows;
7+
using System.Windows.Controls;
8+
using System.Windows.Controls.Primitives;
9+
using System.Windows.Input;
10+
11+
namespace MaterialDesignThemes.Wpf
12+
{
13+
/// <summary>
14+
/// MahApp's validation popup copy
15+
/// </summary>
16+
public sealed class CustomValidationPopup : Popup
17+
{
18+
private Window _hostWindow;
19+
20+
public CustomValidationPopup()
21+
{
22+
this.Loaded += this.CustomValidationPopup_Loaded;
23+
this.Opened += this.CustomValidationPopup_Opened;
24+
}
25+
26+
protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
27+
{
28+
this.IsOpen = false;
29+
}
30+
31+
private void CustomValidationPopup_Loaded(object sender, RoutedEventArgs e)
32+
{
33+
var target = this.PlacementTarget as FrameworkElement;
34+
if (target == null)
35+
{
36+
return;
37+
}
38+
39+
this._hostWindow = Window.GetWindow(target);
40+
if (this._hostWindow == null)
41+
{
42+
return;
43+
}
44+
45+
this._hostWindow.LocationChanged -= this.hostWindow_SizeOrLocationChanged;
46+
this._hostWindow.LocationChanged += this.hostWindow_SizeOrLocationChanged;
47+
this._hostWindow.SizeChanged -= this.hostWindow_SizeOrLocationChanged;
48+
this._hostWindow.SizeChanged += this.hostWindow_SizeOrLocationChanged;
49+
target.SizeChanged -= this.hostWindow_SizeOrLocationChanged;
50+
target.SizeChanged += this.hostWindow_SizeOrLocationChanged;
51+
this._hostWindow.StateChanged -= this.hostWindow_StateChanged;
52+
this._hostWindow.StateChanged += this.hostWindow_StateChanged;
53+
this._hostWindow.Activated -= this.hostWindow_Activated;
54+
this._hostWindow.Activated += this.hostWindow_Activated;
55+
this._hostWindow.Deactivated -= this.hostWindow_Deactivated;
56+
this._hostWindow.Deactivated += this.hostWindow_Deactivated;
57+
58+
this.Unloaded -= this.CustomValidationPopup_Unloaded;
59+
this.Unloaded += this.CustomValidationPopup_Unloaded;
60+
}
61+
62+
private void CustomValidationPopup_Opened(object sender, EventArgs e)
63+
{
64+
//this.SetTopmostState(true);
65+
}
66+
67+
private void hostWindow_Activated(object sender, EventArgs e)
68+
{
69+
//this.SetTopmostState(true);
70+
}
71+
72+
private void hostWindow_Deactivated(object sender, EventArgs e)
73+
{
74+
//this.SetTopmostState(false);
75+
}
76+
77+
private void CustomValidationPopup_Unloaded(object sender, RoutedEventArgs e)
78+
{
79+
var target = this.PlacementTarget as FrameworkElement;
80+
if (target != null)
81+
{
82+
target.SizeChanged -= this.hostWindow_SizeOrLocationChanged;
83+
}
84+
if (this._hostWindow != null)
85+
{
86+
this._hostWindow.LocationChanged -= this.hostWindow_SizeOrLocationChanged;
87+
this._hostWindow.SizeChanged -= this.hostWindow_SizeOrLocationChanged;
88+
this._hostWindow.StateChanged -= this.hostWindow_StateChanged;
89+
this._hostWindow.Activated -= this.hostWindow_Activated;
90+
this._hostWindow.Deactivated -= this.hostWindow_Deactivated;
91+
}
92+
this.Unloaded -= this.CustomValidationPopup_Unloaded;
93+
this.Opened -= this.CustomValidationPopup_Opened;
94+
this._hostWindow = null;
95+
}
96+
97+
private void hostWindow_StateChanged(object sender, EventArgs e)
98+
{
99+
if (this._hostWindow != null && this._hostWindow.WindowState != WindowState.Minimized)
100+
{
101+
var target = this.PlacementTarget as FrameworkElement;
102+
var holder = target != null ? target.DataContext as AdornedElementPlaceholder : null;
103+
if (holder != null && holder.AdornedElement != null)
104+
{
105+
var errorTemplate = holder.AdornedElement.GetValue(Validation.ErrorTemplateProperty);
106+
holder.AdornedElement.SetValue(Validation.ErrorTemplateProperty, null);
107+
holder.AdornedElement.SetValue(Validation.ErrorTemplateProperty, errorTemplate);
108+
}
109+
}
110+
}
111+
112+
private void hostWindow_SizeOrLocationChanged(object sender, EventArgs e)
113+
{
114+
var offset = this.HorizontalOffset;
115+
// "bump" the offset to cause the popup to reposition itself on its own
116+
this.HorizontalOffset = offset + 1;
117+
this.HorizontalOffset = offset;
118+
}
119+
}
120+
}

MaterialDesignThemes.Wpf/MaterialDesignThemes.Wpf.csproj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,10 @@
188188
<SubType>Designer</SubType>
189189
<Generator>MSBuild:Compile</Generator>
190190
</Page>
191+
<Page Include="Themes\MaterialDesignTheme.ValidationErrorTemplate.xaml">
192+
<SubType>Designer</SubType>
193+
<Generator>MSBuild:Compile</Generator>
194+
</Page>
191195
</ItemGroup>
192196
<ItemGroup>
193197
<Compile Include="Card.cs" />
@@ -210,6 +214,7 @@
210214
<Compile Include="Converters\NotZeroToVisibilityConverter.cs" />
211215
<Compile Include="Converters\SizeToRectConverter.cs" />
212216
<Compile Include="CustomPopupPlacementCallbackHelper.cs" />
217+
<Compile Include="CustomValidationPopup.cs" />
213218
<Compile Include="DataGridAssist.cs" />
214219
<Compile Include="DateTimeEx.cs" />
215220
<Compile Include="ListSortDirectionIndicator.cs" />
@@ -241,6 +246,7 @@
241246
<Compile Include="ToolTipAssist.cs" />
242247
<Compile Include="RippleAssist.cs" />
243248
<Compile Include="Ripple.cs" />
249+
<Compile Include="ValidationAssist.cs" />
244250
<EmbeddedResource Include="Properties\Resources.resx">
245251
<Generator>ResXFileCodeGenerator</Generator>
246252
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
@@ -275,6 +281,7 @@
275281
<Name>MaterialDesignColors.Wpf</Name>
276282
</ProjectReference>
277283
</ItemGroup>
284+
<ItemGroup />
278285
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
279286
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
280287
Other similar extension points exist, see Microsoft.Common.targets.

MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.Dark.xaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
<!-- plan is to add all of the light/dark specific brushes, quite granular at first. can then consolodate any repition later on if necessary -->
66

7+
<Color x:Key="ValidationErrorColor">#f44336</Color>
8+
<SolidColorBrush x:Key="ValidationErrorBrush" Color="{StaticResource ValidationErrorColor}"/>
9+
710
<SolidColorBrush x:Key="MaterialDesignBackground" Color="#FF000000"/>
811
<SolidColorBrush x:Key="MaterialDesignPaper" Color="#FF37474f"/>
912
<SolidColorBrush x:Key="MaterialDesignBody" Color="#DDFFFFFF"/>

MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.Defaults.xaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
33

44
<!-- use this resource dictionary to set up the most common themese for standard controls -->
5-
5+
66
<ResourceDictionary.MergedDictionaries>
7+
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.ValidationErrorTemplate.xaml" />
78
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Shadows.xaml" />
89
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/materialdesigntheme.button.xaml" />
910
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.calendar.xaml" />

MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.Light.xaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
22
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
3-
3+
44
<!-- plan is to add all of the light/dark specific brushes, quite granular at first. can then consolodate any repition later on if necessary -->
5+
<Color x:Key="ValidationErrorColor">#f44336</Color>
6+
<SolidColorBrush x:Key="ValidationErrorBrush" Color="{StaticResource ValidationErrorColor}"/>
57

68
<SolidColorBrush x:Key="MaterialDesignBackground" Color="#FFFFFFFF"/>
79
<SolidColorBrush x:Key="MaterialDesignPaper" Color="#FFfafafa"/>

MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.TextBox.xaml

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
<converters:TextFieldHintVisibilityConverter x:Key="TextFieldHintVisibilityConverter" />
77

8+
9+
810
<Style x:Key="MaterialDesignTextBox" TargetType="{x:Type TextBox}">
911
<Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}, Path=(TextElement.Foreground)}"/>
1012
<Setter Property="BorderBrush" Value="{DynamicResource MaterialDesignTextBoxBorder}" />
@@ -19,16 +21,7 @@
1921
<Setter Property="AllowDrop" Value="true"/>
2022
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
2123
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
22-
<Setter Property="Validation.ErrorTemplate">
23-
<Setter.Value>
24-
<ControlTemplate>
25-
<StackPanel>
26-
<AdornedElementPlaceholder />
27-
<TextBlock FontSize="10" Foreground="#f44336" Text="{Binding Path=[0].ErrorContent}" />
28-
</StackPanel>
29-
</ControlTemplate>
30-
</Setter.Value>
31-
</Setter>
24+
<Setter Property="Validation.ErrorTemplate" Value="{DynamicResource MaterialDesignValidationErrorTemplate}"/>
3225
<Setter Property="Template">
3326
<Setter.Value>
3427
<ControlTemplate TargetType="{x:Type TextBox}">
@@ -58,7 +51,7 @@
5851
<Setter Property="BorderBrush" Value="{DynamicResource PrimaryHueMidBrush}"/>
5952
</Trigger>
6053
<Trigger Property="Validation.HasError" Value="true">
61-
<Setter Property="BorderBrush" Value="#f44336"/>
54+
<Setter Property="BorderBrush" Value="{DynamicResource ValidationErrorBrush}"/>
6255
</Trigger>
6356
</ControlTemplate.Triggers>
6457
</ControlTemplate>
@@ -163,7 +156,7 @@
163156
<Setter Property="BorderBrush" Value="{DynamicResource PrimaryHueMidBrush}"/>
164157
</Trigger>
165158
<Trigger Property="Validation.HasError" Value="true">
166-
<Setter Property="BorderBrush" Value="#f44336"/>
159+
<Setter Property="BorderBrush" Value="{DynamicResource ValidationErrorBrush}"/>
167160
</Trigger>
168161
</ControlTemplate.Triggers>
169162
</ControlTemplate>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
2+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3+
xmlns:wpf="clr-namespace:MaterialDesignThemes.Wpf">
4+
5+
<ControlTemplate x:Key="MaterialDesignValidationErrorTemplate">
6+
<StackPanel>
7+
<AdornedElementPlaceholder Name="Placeholder" />
8+
<wpf:CustomValidationPopup x:Name="ValidationPopup"
9+
IsOpen="True"
10+
Placement="Bottom" PlacementTarget="{Binding ElementName=Placeholder}"
11+
AllowsTransparency="True">
12+
<Border Background="{DynamicResource MaterialDesignPaper}">
13+
<Border.Resources>
14+
<DataTemplate DataType="{x:Type ValidationError}">
15+
<TextBlock Foreground="{DynamicResource ValidationErrorBrush}"
16+
FontSize="10"
17+
MaxWidth="250"
18+
Margin="2"
19+
TextWrapping="Wrap"
20+
Text="{Binding ErrorContent}"
21+
UseLayoutRounding="false" />
22+
</DataTemplate>
23+
</Border.Resources>
24+
<ContentPresenter Content="{Binding CurrentItem}" />
25+
</Border>
26+
</wpf:CustomValidationPopup>
27+
</StackPanel>
28+
<ControlTemplate.Triggers>
29+
<DataTrigger Binding="{Binding ElementName=Placeholder, Path=AdornedElement.(wpf:ValidationAssist.ShowOnFocus)}" Value="True">
30+
<Setter TargetName="ValidationPopup" Property="IsOpen" Value="{Binding ElementName=Placeholder, Path=AdornedElement.IsKeyboardFocusWithin, Mode=OneWay}"/>
31+
</DataTrigger>
32+
</ControlTemplate.Triggers>
33+
</ControlTemplate>
34+
</ResourceDictionary>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using System.Windows;
7+
8+
namespace MaterialDesignThemes.Wpf
9+
{
10+
public static class ValidationAssist
11+
{
12+
#region ShowOnFocusProperty
13+
14+
/// <summary>
15+
/// The hint property
16+
/// </summary>
17+
public static readonly DependencyProperty ShowOnFocusProperty = DependencyProperty.RegisterAttached(
18+
"ShowOnFocus",
19+
typeof(bool),
20+
typeof(ValidationAssist),
21+
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits));
22+
23+
public static bool GetShowOnFocus(DependencyObject element)
24+
{
25+
return (bool) element.GetValue(ShowOnFocusProperty);
26+
}
27+
28+
public static void SetShowOnFocus(DependencyObject element, bool value)
29+
{
30+
element.SetValue(ShowOnFocusProperty, value);
31+
}
32+
33+
#endregion
34+
}
35+
}

0 commit comments

Comments
 (0)