Results 1 to 1 of 1
  1. #1
    Zyztems
    Zyztems is offline
    Guest
    Join Date
    2014 Aug
    Posts
    1
    Thanks Thanks Given 
    0
    Thanks Thanks Received 
    0
    Thanked in
    0 Posts
    Rep Power
    0

    ErrorTemplate for WPF

    Hi,

    This is a little piece of code to display beautiful popups like errors for WPF with the pattern MVVM.

    First the Behavior

    Code:
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Controls.Primitives;
    
    public class PopupBehavior
    {
        private static bool showOnActivated;
    
        public static FrameworkElement GetReLocation(DependencyObject obj)
        {
            return (FrameworkElement)obj.GetValue(ReLocationProperty);
        }
    
        public static void SetReLocation(DependencyObject obj, FrameworkElement value)
        {
            obj.SetValue(ReLocationProperty, value);
        }
    
        public static readonly DependencyProperty ReLocationProperty = DependencyProperty.RegisterAttached(
            "ReLocation",
            typeof(FrameworkElement),
            typeof(PopupBehavior),
            new UIPropertyMetadata(OnReLocationPropertyChanged));
    
        private static void OnReLocationPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            if (DesignerProperties.GetIsInDesignMode(obj))
            {
                return;
            }
    
            if (obj == null)
            {
                return;
            }
    
            var element = obj as UIElement;
            if (element == null)
            {
                return;
            }
    
            var popup = args.NewValue as Popup;
            if (popup == null)
            {
                return;
            }
    
            SetUpReLocation(element, popup);
        }
    
        private static void SetUpReLocation(UIElement element, Popup popup)
        {
            var window = Window.GetWindow(element);
                
            if (null == window)
            {
                return;
            }
    
            window.LocationChanged += (sender, args) => RedrawPopup(popup);
    
            window.SizeChanged += (sender, args) => RedrawPopup(popup);
    
            window.Activated += (sender, args) => ActivatedPopup(popup);
    
            window.Deactivated += (sender, args) => DeactivatedPopup(popup);
        }
    
        private static void RedrawPopup(Popup popup)
        {
            var offset = popup.HorizontalOffset;
            popup.HorizontalOffset = offset + 1;
            popup.HorizontalOffset = offset;
        }
    
        private static void ActivatedPopup(Popup popup)
        {
            if (!showOnActivated)
            {
                return;
            }
    
            popup.IsOpen = true;
            showOnActivated = false;
        }
    
        private static void DeactivatedPopup(Popup popup)
        {
            if (!popup.IsOpen)
            {
                return;
            }
    
            popup.IsOpen = false;
            showOnActivated = true;
        }
    }
    This allow you to show, hide and more automatic interactivity with the popup of the error.

    Now the template

    Code:
    <ControlTemplate x:Key="ErrorTemplate">
        <Grid>
            <Border x:Name="ErrorBorder" Background="#11FF0000" IsHitTestVisible="False" 
                    BorderBrush="#FFCB2E2E" BorderThickness="1"
                    radEx:PopupBehavior.ReLocation="{Binding ElementName=ErrorPopup}"/>
            <AdornedElementPlaceholder x:Name="Placeholder" />
            <Popup x:Name="ErrorPopup"
                    AllowsTransparency="True" 
                    HorizontalAlignment="Right" 
                    HorizontalOffset="0" 
                    VerticalOffset="0" 
                    PopupAnimation="Fade" 
                    Placement="Right" 
                    PlacementTarget="{Binding ElementName=ErrorBorder}" 
                    IsOpen="{Binding ElementName=Placeholder, Path=AdornedElement.IsFocused, Mode=OneWay}">
                <StackPanel Orientation="Horizontal">
                    <Polygon VerticalAlignment="Center" Points="0,4 4,0 4,8" Fill="#FFCB2E2E" 
                                                            Stretch="Fill" Stroke="#FFCB2E2E" StrokeThickness="2" />
                    <Border Background="#FFCB2E2E" CornerRadius="4" Padding="4">
                        <TextBlock HorizontalAlignment="Center" Foreground="White" FontWeight="Bold" Margin="2,0,0,0"
                                                                Text="{Binding ElementName=Placeholder, Path=AdornedElement.ToolTip, Mode=OneWay}" />
                    </Border>
                </StackPanel>
            </Popup>
        </Grid>
    </ControlTemplate>
    Dont forget declare the namespace where you set the behavior

    Code:
    xmlns:radEx="clr-namespace:[TheNamespaceWhereYouDefineTheBehavior]"
    Near to end we define the style, in this case for a TextBox

    Code:
    <Style x:Key="TextBoxError" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBoxBase}}">
        <Setter Property="Validation.ErrorTemplate" Value="{StaticResource ErrorTemplate}"/>
        <Style.Triggers>
            <Trigger Property="Validation.HasError" Value="True">
                <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
            </Trigger>
        </Style.Triggers>
    </Style>

    And at the end apply this to a TextBox

    Code:
    <TextBox 
    Text="{Binding Path=MyMVMMText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, NotifyOnValidationError=True, ValidatesOnDataErrors=True}" 
    TextAlignment="Right"
    Style="{StaticResource TextBoxError}"/>

    Thats all for get nice error displays on controls.

    Like all ControlTemplate can style any control.

    Have a nice day!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •