CSLA .NET

Vibrant discussion about CSLA .NET and using the framework to build great business applications.

Forum has moved

New location: CSLA .NET forum


CSLA .NET Resources:
  • CSLA .NET forum
  • CSLA .NET home page
  • PropertyInfo Control in CaliburnMicro

    rated by 0 users
    Answered (Verified) This post has 1 verified answer | 4 Replies | 3 Followers

    Not Ranked
    6 Posts
    blc303 posted on Mon, Oct 8 2012 8:44 AM

    Does anyone have an example of a Style for a TextBox using the PropertyInfo Control with CaliburnMicro?

     

    I have been trying to cobble something together based on the WP example but have had absolutely no success.

     

    I get the impression that the DataTriggers aren't firing but I have no idea what I am doing wrong. I suspect the Binding is completely wrong.

    Here is my relatively primitive start.

                <LinearGradientBrush x:Key="TextBoxBorder" EndPoint="0,20" MappingMode="Absolute" StartPoint="0,0">
                    <GradientStop Color="#ABADB3" Offset="0.05"/>
                    <GradientStop Color="#E2E3EA" Offset="0.07"/>
                    <GradientStop Color="#E3E9EF" Offset="1"/>
                </LinearGradientBrush>
                
                <SolidColorBrush x:Key="ValidatonBorderBrushWarning" Color="#F0F0CA00"/>
                <SolidColorBrush x:Key="ValidatonBorderBrushError" Color="#FFC1121C"/>
                <SolidColorBrush x:Key="ValidatonBorderBrushInfo" Color="#FF1174EC"/>
                <CornerRadius x:Key="TextBoxCornerRadius">5</CornerRadius>
                <SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" />
                <SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#EEE" />
                <SolidColorBrush x:Key="WindowBackgroundBrush" Color="#FFF" />
                <SolidColorBrush x:Key="SelectedBackgroundBrush" Color="#DDD" />
    
                <Style x:Key="CSLATextBox" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
                    <Setter Property="SnapsToDevicePixels" Value="True"/>
                    <Setter Property="OverridesDefaultStyle" Value="True"/>
                    <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
                    <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
                    <Setter Property="MinWidth" Value="120"/>
                    <Setter Property="MinHeight" Value="20"/>
                    <Setter Property="AllowDrop" Value="true"/>
    
                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
                    <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type TextBox}">
                                <Grid>
                                    <Border x:Name="ValidationElement" 
                                        CornerRadius="{StaticResource TextBoxCornerRadius}" 
                                        Padding="2"     
                                        BorderThickness="2"
                                        BorderBrush="{StaticResource ValidatonBorderBrushError}"
                                        Visibility="Collapsed">
                                        <Grid HorizontalAlignment="Right" 
                                          VerticalAlignment="Top" 
                                          Margin="0,-4,-4,0"
                                          Height="14" 
                                          Width="14">
                                            <Path Data="M0,0 L15,0 14,14" 
                                              Fill="{StaticResource ValidatonBorderBrushError}" />
                                            <Path Margin="0,0,0,0" Data="M 0,0 L2,0 L 14,12 L14,14" Fill="#ffffff"/>                                        
                                        </Grid>
                                    </Border>
    
                                    <Border Name="Border"
                                        CornerRadius="{StaticResource TextBoxCornerRadius}" 
                                        Padding="2"     
                                        BorderThickness="1"                            
                                        BorderBrush="{StaticResource TextBoxBorder}"
                                        Visibility="Visible" >
                                    </Border>
                                    
                                    <StackPanel Orientation="Horizontal">
                                        <ScrollViewer Margin="2" x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>                                    
                                    </StackPanel>
                                    
                                    <csla:PropertyInfo Property="{Binding Text, RelativeSource={RelativeSource TemplatedParent}}" x:Name="pi">
                                        <i:Interaction.Triggers>
                                            <ei:DataTrigger Binding="{Binding Path=RuleSeverity, ElementName=pi}">
                                                <ei:DataTrigger.Value>
                                                    <cslaRules:RuleSeverity>Error</cslaRules:RuleSeverity>
                                                </ei:DataTrigger.Value>
                                                <ei:ChangePropertyAction 
                                                TargetName="ValidationElement" 
                                                PropertyName="BorderBrush"
                                                Value="{StaticResource ValidatonBorderBrushError}"/>
                                                <ei:ChangePropertyAction 
                                                TargetName="ValidationElement" 
                                                PropertyName="Visibility"
                                                Value="Visible"/>
                                                <ei:ChangePropertyAction 
                                                TargetName="Border" 
                                                PropertyName="Visibility"
                                                Value="Collapsed"/>                                            
                                            </ei:DataTrigger>
                                            <ei:DataTrigger Binding="{Binding Path=RuleSeverity, ElementName=pi}">
                                                <ei:DataTrigger.Value>
                                                    <cslaRules:RuleSeverity>Warning</cslaRules:RuleSeverity>
                                                </ei:DataTrigger.Value>
                                                <ei:ChangePropertyAction 
                                                TargetName="ValidationElement" 
                                                PropertyName="BorderBrush"
                                                Value="{StaticResource ValidatonBorderBrushWarning}"/>
                                                <ei:ChangePropertyAction 
                                                TargetName="ValidationElement" 
                                                PropertyName="Visibility"
                                                Value="Visible"/>
                                                <ei:ChangePropertyAction 
                                                TargetName="Border" 
                                                PropertyName="Visibility"
                                                Value="Collapsed"/>
                                            </ei:DataTrigger>
                                            <ei:DataTrigger Binding="{Binding Path=RuleSeverity, ElementName=pi}">
                                                <ei:DataTrigger.Value>
                                                    <cslaRules:RuleSeverity>Information</cslaRules:RuleSeverity>
                                                </ei:DataTrigger.Value>
                                                <ei:ChangePropertyAction 
                                                TargetName="ValidationElement" 
                                                PropertyName="BorderBrush"
                                                Value="{StaticResource ValidatonBorderBrushInfo}"/>
                                                <ei:ChangePropertyAction 
                                                TargetName="ValidationElement" 
                                                PropertyName="Visibility"
                                                Value="Visible"/>
                                                <ei:ChangePropertyAction 
                                                TargetName="Border" 
                                                PropertyName="Visibility"
                                                Value="Collapsed"/>
                                            </ei:DataTrigger>
                                            <ei:DataTrigger Binding="{Binding Path=RuleSeverity, ElementName=pi}">
                                                <ei:DataTrigger.Value>
                                                    <cslaRules:RuleSeverity>Information</cslaRules:RuleSeverity>
                                                </ei:DataTrigger.Value>
                                                <ei:ChangePropertyAction 
                                                TargetName="ValidationElement" 
                                                PropertyName="BorderBrush"
                                                Value="{StaticResource ValidatonBorderBrushInfo}"/>
                                                <ei:ChangePropertyAction 
                                                TargetName="ValidationElement" 
                                                PropertyName="Visibility"
                                                Value="Visible"/>
                                                <ei:ChangePropertyAction 
                                                TargetName="Border" 
                                                PropertyName="Visibility"
                                                Value="Collapsed"/>
                                            </ei:DataTrigger>
    
                                            <ei:DataTrigger Binding="{Binding CanRead, ElementName=pi}" Value="False">
                                                <ei:ChangePropertyAction TargetObject="{Binding RelativeSource={RelativeSource TemplatedParent}}" 
                                                           PropertyName="Visibility" Value="Collapsed" />
                                            </ei:DataTrigger>
                                            <ei:DataTrigger Binding="{Binding CanWrite, ElementName=pi}" Value="False">
                                                <ei:ChangePropertyAction TargetObject="{Binding RelativeSource={RelativeSource TemplatedParent}}" 
                                                           PropertyName="IsReadOnly" Value="True" />
                                            </ei:DataTrigger>
                                        </i:Interaction.Triggers>
                                    </csla:PropertyInfo>
                                </Grid>
    
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsEnabled" Value="False">
                                        <Setter TargetName="Border" Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                                        <Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource DisabledBackgroundBrush}"/>
                                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
    

    Anyone have any suggestions? Thanks

    Answered (Verified) Verified Answer

    Not Ranked
    2 Posts
    Verified by blc303

    Below is a sample WPF TextBox template that incorporates validation, authorization, and property busy status for a CSLA object. This example supports warning and information level errors as well as the normal validation errors. Authorization rules are handled by collapsing the textbox if the user does not have permission to read the property, and marks the textbox as read only if the user does not have write permissions.

    Obviously you can tailor the template to your needs, but I hope this gets you a good start.

    xmlns:csla="clr-namespace:Csla.Xaml;assembly=Csla.Xaml"
    xmlns:cslaRules="clr-namespace:Csla.Rules;assembly=Csla"
    xmlns:i=http://schemas.microsoft.com/expression/2010/interactivity
    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"

    <SolidColorBrush x:Key="ValidationBrush_Error" Color="#FFDC000C"/>
    <SolidColorBrush x:Key="ValidationBrush_Warning" Color="#FFEBF900"/>
    <SolidColorBrush x:Key="ValidationBrush_Info" Color="#FF0000FF"/>

    <Style x:Key="TextBoxStyle" TargetType="TextBox">
        <Setter Property="Margin" Value="0,1,10,1"/>
        <Setter Property="VerticalAlignment" Value="Stretch"/>
        <Setter Property="FontFamily" Value="Segoe WP"/>
        <Setter Property="Height" Value="30" />
        <Setter Property="MinWidth" Value="200" />
        <Setter Property="FontSize" Value="16" />
        <Setter Property="VerticalContentAlignment" Value="Center" />   
        <Setter Property="BorderBrush" Value="White" />
        <Setter Property="Template">
          <Setter.Value>
            <ControlTemplate TargetType="TextBox">
                <Grid x:Name="RootElement">
                  <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name="CommonStates">
                      <VisualState x:Name="Normal"/>
                      <VisualState x:Name="MouseOver">
                        <Storyboard>
                          <ColorAnimation Storyboard.TargetName="MouseOverBorder" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" To="#FF99C1E2" Duration="0"/>
                        </Storyboard>
                      </VisualState>
                      <VisualState x:Name="Disabled">
                        <Storyboard>
                          <DoubleAnimation Storyboard.TargetName="DisabledVisualElement" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
                        </Storyboard>
                      </VisualState>
                      <VisualState x:Name="ReadOnly">
                        <Storyboard>
                          <DoubleAnimation Storyboard.TargetName="ReadOnlyVisualElement" Storyboard.TargetProperty="Opacity" To="1" Duration="0" />
                        </Storyboard>
                      </VisualState>
                    </VisualStateGroup>
                    <VisualStateGroup x:Name="FocusStates">
                      <VisualState x:Name="Focused">
                        <Storyboard>
                          <DoubleAnimation Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
                        </Storyboard>
                      </VisualState>
                      <VisualState x:Name="Unfocused">
                        <Storyboard>
                          <DoubleAnimation Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity" To="0" Duration="0"/>
                        </Storyboard>
                      </VisualState>
                    </VisualStateGroup>
                    <VisualStateGroup x:Name="CslaValidationStates">
                      <VisualState x:Name="CslaValid"/>
                      <VisualState x:Name="CslaInvalidUnfocused">
                        <Storyboard>
                          <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ValidationErrorElement" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0">
                              <DiscreteObjectKeyFrame.Value>
                                <Visibility>Visible</Visibility>
                              </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                          </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                      </VisualState>
                      <VisualState x:Name="CslaInvalidFocused">
                        <Storyboard>
                          <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ValidationErrorElement" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0">
                              <DiscreteObjectKeyFrame.Value>
                                <Visibility>Visible</Visibility>
                              </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                          </ObjectAnimationUsingKeyFrames>
                          <ObjectAnimationUsingKeyFrames Storyboard.TargetName="validationPopup" Storyboard.TargetProperty="IsOpen">
                            <DiscreteObjectKeyFrame KeyTime="0">
                              <DiscreteObjectKeyFrame.Value>
                                <System:Boolean>True</System:Boolean>
                              </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                          </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                      </VisualState>
                    </VisualStateGroup>
                    <VisualStateGroup x:Name="BusyStates">
                      <VisualState x:Name="Idle"/>
                      <VisualState x:Name="Busy">
                        <Storyboard>
                          <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="BusyElement" RepeatBehavior="Forever">
                            <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1">
                              <EasingDoubleKeyFrame.EasingFunction>
                                <QuinticEase EasingMode="EaseIn"/>
                              </EasingDoubleKeyFrame.EasingFunction>
                            </EasingDoubleKeyFrame>
                            <EasingDoubleKeyFrame KeyTime="0:0:1" Value="0"/>
                          </DoubleAnimationUsingKeyFrames>
                        </Storyboard>
                      </VisualState>
                    </VisualStateGroup>
                  </VisualStateManager.VisualStateGroups>

                  <Border x:Name="Border" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="0" Opacity="1" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}">
                    <Grid>
                      <Border x:Name="ReadOnlyVisualElement" Opacity="0" Background="#5EC9C9C9"/>
                      <Border x:Name="MouseOverBorder" BorderThickness="1" BorderBrush="Transparent">
                        <ScrollViewer x:Name="PART_ContentHost" Padding="{TemplateBinding Padding}" BorderThickness="0" IsTabStop="False"/>
                      </Border>
                    </Grid>
                  </Border>
                  <Border x:Name="DisabledVisualElement" Background="#A5F7F7F7" BorderBrush="#A5F7F7F7" BorderThickness="{TemplateBinding BorderThickness}" Opacity="0" IsHitTestVisible="False"/>
                  <Border x:Name="FocusVisualElement" BorderBrush="#FF212B40" BorderThickness="{TemplateBinding BorderThickness}" Margin="0" Opacity="0" IsHitTestVisible="False"/>
                  <Border x:Name="ValidationErrorElement" BorderThickness="1" CornerRadius="0" BorderBrush="{StaticResource ValidationBrush_Error}" Visibility="Collapsed">
                    <Grid>
                      <Popup x:Name="validationPopup"
                               AllowsTransparency="True"
                               PopupAnimation="None"
                               Placement="Bottom"
                               PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
                               DataContext="{Binding ElementName=pi}"
                               VerticalOffset="-25">
                        <Grid x:Name="Root" Margin="0" Opacity="0">
                          <Border x:Name="validationPopupBorder" Background="{StaticResource ValidationBrush_Error}" CornerRadius="0"/>
                          <Border CornerRadius="0">
                            <TextBlock x:Name="validationPopupText"
                                         UseLayoutRounding="false"
                                         Foreground="White"
                                         FontSize="11"
                                         Margin="8,4,8,4"
                                         MaxWidth="250"
                                         TextWrapping="Wrap"
                                         Text="{Binding Path=RuleDescription}" />
                          </Border>
                        </Grid>
                      </Popup>
                      <Grid Width="12" Height="12" HorizontalAlignment="Right" Margin="1,-4,-4,0" VerticalAlignment="Top" Background="Transparent">
                        <Path Margin="1,3,0,0" Data="M 1,0 L6,0 A 2,2 90 0 1 8,2 L8,7 z" x:Name="ValidationErrorElement_Path" Fill="{StaticResource ValidationBrush_Error}"/>
                        <Path Margin="1,3,0,0" Data="M 0,0 L2,0 L 8,6 L8,8" Fill="#ffffff"/>
                      </Grid>
                    </Grid>
                  </Border>
                  <Rectangle x:Name="BusyElement" Fill="#FF7A7A7A" HorizontalAlignment="Right" Width="12" Height="12" VerticalAlignment="Center" Margin="5,5,10,5" Opacity="0"/>

                  <csla:PropertyInfo Property="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Text}" x:Name="pi">
                    <i:Interaction.Triggers>
                      <ei:DataTrigger Binding="{Binding Path=RuleSeverity, ElementName=pi}">
                        <ei:DataTrigger.Value>
                          <cslaRules:RuleSeverity>Error</cslaRules:RuleSeverity>
                        </ei:DataTrigger.Value>
                        <ei:ChangePropertyAction TargetName="validationPopupText"
                                                 PropertyName="Foreground"
                                                 Value="White" />
                        <ei:ChangePropertyAction TargetName="validationPopupBorder"
                                                 PropertyName="Background"
                                                 Value="{StaticResource ValidationBrush_Error}" />
                        <ei:ChangePropertyAction TargetName="ValidationErrorElement"
                                                 PropertyName="BorderBrush"
                                                 Value="{StaticResource ValidationBrush_Error}" />
                        <ei:ChangePropertyAction TargetName="ValidationErrorElement_Path"
                                                 PropertyName="Fill"
                                                 Value="{StaticResource ValidationBrush_Error}" />
                      </ei:DataTrigger>

                      <ei:DataTrigger Binding="{Binding Path=RuleSeverity, ElementName=pi}">
                        <ei:DataTrigger.Value>
                          <cslaRules:RuleSeverity>Warning</cslaRules:RuleSeverity>
                        </ei:DataTrigger.Value>
                        <ei:ChangePropertyAction TargetName="validationPopupText"
                                                 PropertyName="Foreground"
                                                 Value="Black" />
                        <ei:ChangePropertyAction TargetName="validationPopupBorder"
                                                 PropertyName="Background"
                                                 Value="{StaticResource ValidationBrush_Warning}" />
                        <ei:ChangePropertyAction TargetName="ValidationErrorElement"
                                                 PropertyName="BorderBrush"
                                                 Value="{StaticResource ValidationBrush_Warning}" />
                        <ei:ChangePropertyAction TargetName="ValidationErrorElement_Path"
                                                 PropertyName="Fill"
                                                 Value="{StaticResource ValidationBrush_Warning}" />
                      </ei:DataTrigger>

                      <ei:DataTrigger Binding="{Binding Path=RuleSeverity, ElementName=pi}">
                        <ei:DataTrigger.Value>
                          <cslaRules:RuleSeverity>Information</cslaRules:RuleSeverity>
                        </ei:DataTrigger.Value>
                        <ei:ChangePropertyAction TargetName="validationPopupText"
                                                 PropertyName="Foreground"
                                                 Value="White" />
                        <ei:ChangePropertyAction TargetName="validationPopupBorder"
                                                 PropertyName="Background"
                                                 Value="{StaticResource ValidationBrush_Info}" />
                        <ei:ChangePropertyAction TargetName="ValidationErrorElement"
                                                 PropertyName="BorderBrush"
                                                 Value="{StaticResource ValidationBrush_Info}" />
                        <ei:ChangePropertyAction TargetName="ValidationErrorElement_Path"
                                                 PropertyName="Fill"
                                                 Value="{StaticResource ValidationBrush_Info}" />
                      </ei:DataTrigger>

                      <i:EventTrigger SourceObject="{Binding RelativeSource={RelativeSource TemplatedParent}}" EventName="GotFocus">
                        <i:Interaction.Behaviors>
                          <ei:ConditionBehavior>
                            <ei:ConditionalExpression>
                              <ei:ComparisonCondition LeftOperand="{Binding IsValid, ElementName=pi}" RightOperand="False"/>
                            </ei:ConditionalExpression>
                          </ei:ConditionBehavior>
                        </i:Interaction.Behaviors>
                        <ei:GoToStateAction StateName="CslaInvalidFocused"/>
                      </i:EventTrigger>
                      <i:EventTrigger SourceObject="{Binding RelativeSource={RelativeSource TemplatedParent}}" EventName="LostFocus">
                        <i:Interaction.Behaviors>
                          <ei:ConditionBehavior>
                            <ei:ConditionalExpression>
                              <ei:ComparisonCondition LeftOperand="{Binding IsValid, ElementName=pi}" RightOperand="False"/>
                            </ei:ConditionalExpression>
                          </ei:ConditionBehavior>
                        </i:Interaction.Behaviors>
                        <ei:GoToStateAction StateName="CslaInvalidUnfocused"/>
                      </i:EventTrigger>
                      <ei:DataTrigger Binding="{Binding IsValid, ElementName=pi}" Value="False">
                        <ei:GoToStateAction StateName="CslaInvalidUnfocused"/>
                      </ei:DataTrigger>
                      <ei:DataTrigger Binding="{Binding IsValid, ElementName=pi}" Value="True">
                        <ei:GoToStateAction StateName="CslaValid"/>
                      </ei:DataTrigger>

                      <ei:DataTrigger Binding="{Binding IsBusy, ElementName=pi}" Value="True">
                        <ei:GoToStateAction StateName="Busy"/>
                      </ei:DataTrigger>
                      <ei:DataTrigger Binding="{Binding IsBusy, ElementName=pi}" Value="False">
                        <ei:GoToStateAction StateName="Idle"/>
                      </ei:DataTrigger>

                      <ei:DataTrigger Binding="{Binding CanRead, ElementName=pi}" Value="False">
                        <ei:ChangePropertyAction TargetObject="{Binding RelativeSource={RelativeSource TemplatedParent}}"
                                                   PropertyName="Visibility" Value="Collapsed" />
                      </ei:DataTrigger>
                      <ei:DataTrigger Binding="{Binding CanWrite, ElementName=pi}" Value="False">
                        <ei:ChangePropertyAction TargetObject="{Binding RelativeSource={RelativeSource TemplatedParent}}"
                                                   PropertyName="IsReadOnly" Value="True" />
                      </ei:DataTrigger>
                    </i:Interaction.Triggers>
                  </csla:PropertyInfo>

                </Grid>

                <ControlTemplate.Triggers>
                  <DataTrigger Binding="{Binding ElementName=validationPopup, Path=IsOpen}" Value="True">
                    <DataTrigger.EnterActions>
                      <BeginStoryboard>
                        <Storyboard>
                          <DoubleAnimation Storyboard.TargetName="validationPopup" Storyboard.TargetProperty="VerticalOffset" To="0" Duration="0:0:0.2">
                            <DoubleAnimation.EasingFunction>
                              <BackEase Amplitude=".3" EasingMode="EaseOut"/>
                            </DoubleAnimation.EasingFunction>
                          </DoubleAnimation>
                          <DoubleAnimation Storyboard.TargetName="Root" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.2"/>
                        </Storyboard>
                      </BeginStoryboard>
                    </DataTrigger.EnterActions>
                    <DataTrigger.ExitActions>
                      <BeginStoryboard>
                        <Storyboard>
                          <DoubleAnimation Storyboard.TargetName="validationPopup" Storyboard.TargetProperty="VerticalOffset" To="-25" Duration="0:0:0.2">
                            <DoubleAnimation.EasingFunction>
                              <BackEase Amplitude=".3" EasingMode="EaseOut"/>
                            </DoubleAnimation.EasingFunction>
                          </DoubleAnimation>
                          <DoubleAnimation Storyboard.TargetName="Root" Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.2"/>
                        </Storyboard>
                      </BeginStoryboard>
                    </DataTrigger.ExitActions>
                  </DataTrigger>
                </ControlTemplate.Triggers>
              </ControlTemplate>         
          </Setter.Value>
        </Setter>
    </Style> 

    All Replies

    Top 10 Contributor
    9,475 Posts

    Make sure you are running the latest 4.3 build. There were some bug fixes in PropertyInfo to deal with issues like you are encountering.

    Rocky

    Not Ranked
    2 Posts

    I'd be happy to help you out. Can you describe which features of PropertyInfo you want to implement (i.e. - authorization, validation, or both)? Also, it looks like you're using WPF, can you confirm that?

    Thanks,
    Aaron

    Not Ranked
    6 Posts

    @Rocky, I am running Version 4.3.13.0

     

    @Aaron

    Yes, I am working with WPF.

    I my first concern is validation but I am working on a WPF Caliburn / CSLA Framework and would like to eventually include authorization if possible.

    What I would love is a dead simple, self-contained  WPF example showing on a text validation (maybe change the background color) and authorization (Collapse or Disable). By self-contained I mean no external color resources, formatting etc. I should be able to adapt from there or perhaps see what I am doing wrong.

    My main problem is that with the amount of behind the scenes data binding going on, it's really difficult to actually see what isn't working.

    I would be forever grateful if you had something like that.

    Thanks

    Not Ranked
    2 Posts
    Verified by blc303

    Below is a sample WPF TextBox template that incorporates validation, authorization, and property busy status for a CSLA object. This example supports warning and information level errors as well as the normal validation errors. Authorization rules are handled by collapsing the textbox if the user does not have permission to read the property, and marks the textbox as read only if the user does not have write permissions.

    Obviously you can tailor the template to your needs, but I hope this gets you a good start.

    xmlns:csla="clr-namespace:Csla.Xaml;assembly=Csla.Xaml"
    xmlns:cslaRules="clr-namespace:Csla.Rules;assembly=Csla"
    xmlns:i=http://schemas.microsoft.com/expression/2010/interactivity
    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"

    <SolidColorBrush x:Key="ValidationBrush_Error" Color="#FFDC000C"/>
    <SolidColorBrush x:Key="ValidationBrush_Warning" Color="#FFEBF900"/>
    <SolidColorBrush x:Key="ValidationBrush_Info" Color="#FF0000FF"/>

    <Style x:Key="TextBoxStyle" TargetType="TextBox">
        <Setter Property="Margin" Value="0,1,10,1"/>
        <Setter Property="VerticalAlignment" Value="Stretch"/>
        <Setter Property="FontFamily" Value="Segoe WP"/>
        <Setter Property="Height" Value="30" />
        <Setter Property="MinWidth" Value="200" />
        <Setter Property="FontSize" Value="16" />
        <Setter Property="VerticalContentAlignment" Value="Center" />   
        <Setter Property="BorderBrush" Value="White" />
        <Setter Property="Template">
          <Setter.Value>
            <ControlTemplate TargetType="TextBox">
                <Grid x:Name="RootElement">
                  <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name="CommonStates">
                      <VisualState x:Name="Normal"/>
                      <VisualState x:Name="MouseOver">
                        <Storyboard>
                          <ColorAnimation Storyboard.TargetName="MouseOverBorder" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" To="#FF99C1E2" Duration="0"/>
                        </Storyboard>
                      </VisualState>
                      <VisualState x:Name="Disabled">
                        <Storyboard>
                          <DoubleAnimation Storyboard.TargetName="DisabledVisualElement" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
                        </Storyboard>
                      </VisualState>
                      <VisualState x:Name="ReadOnly">
                        <Storyboard>
                          <DoubleAnimation Storyboard.TargetName="ReadOnlyVisualElement" Storyboard.TargetProperty="Opacity" To="1" Duration="0" />
                        </Storyboard>
                      </VisualState>
                    </VisualStateGroup>
                    <VisualStateGroup x:Name="FocusStates">
                      <VisualState x:Name="Focused">
                        <Storyboard>
                          <DoubleAnimation Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
                        </Storyboard>
                      </VisualState>
                      <VisualState x:Name="Unfocused">
                        <Storyboard>
                          <DoubleAnimation Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity" To="0" Duration="0"/>
                        </Storyboard>
                      </VisualState>
                    </VisualStateGroup>
                    <VisualStateGroup x:Name="CslaValidationStates">
                      <VisualState x:Name="CslaValid"/>
                      <VisualState x:Name="CslaInvalidUnfocused">
                        <Storyboard>
                          <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ValidationErrorElement" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0">
                              <DiscreteObjectKeyFrame.Value>
                                <Visibility>Visible</Visibility>
                              </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                          </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                      </VisualState>
                      <VisualState x:Name="CslaInvalidFocused">
                        <Storyboard>
                          <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ValidationErrorElement" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0">
                              <DiscreteObjectKeyFrame.Value>
                                <Visibility>Visible</Visibility>
                              </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                          </ObjectAnimationUsingKeyFrames>
                          <ObjectAnimationUsingKeyFrames Storyboard.TargetName="validationPopup" Storyboard.TargetProperty="IsOpen">
                            <DiscreteObjectKeyFrame KeyTime="0">
                              <DiscreteObjectKeyFrame.Value>
                                <System:Boolean>True</System:Boolean>
                              </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                          </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                      </VisualState>
                    </VisualStateGroup>
                    <VisualStateGroup x:Name="BusyStates">
                      <VisualState x:Name="Idle"/>
                      <VisualState x:Name="Busy">
                        <Storyboard>
                          <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="BusyElement" RepeatBehavior="Forever">
                            <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1">
                              <EasingDoubleKeyFrame.EasingFunction>
                                <QuinticEase EasingMode="EaseIn"/>
                              </EasingDoubleKeyFrame.EasingFunction>
                            </EasingDoubleKeyFrame>
                            <EasingDoubleKeyFrame KeyTime="0:0:1" Value="0"/>
                          </DoubleAnimationUsingKeyFrames>
                        </Storyboard>
                      </VisualState>
                    </VisualStateGroup>
                  </VisualStateManager.VisualStateGroups>

                  <Border x:Name="Border" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="0" Opacity="1" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}">
                    <Grid>
                      <Border x:Name="ReadOnlyVisualElement" Opacity="0" Background="#5EC9C9C9"/>
                      <Border x:Name="MouseOverBorder" BorderThickness="1" BorderBrush="Transparent">
                        <ScrollViewer x:Name="PART_ContentHost" Padding="{TemplateBinding Padding}" BorderThickness="0" IsTabStop="False"/>
                      </Border>
                    </Grid>
                  </Border>
                  <Border x:Name="DisabledVisualElement" Background="#A5F7F7F7" BorderBrush="#A5F7F7F7" BorderThickness="{TemplateBinding BorderThickness}" Opacity="0" IsHitTestVisible="False"/>
                  <Border x:Name="FocusVisualElement" BorderBrush="#FF212B40" BorderThickness="{TemplateBinding BorderThickness}" Margin="0" Opacity="0" IsHitTestVisible="False"/>
                  <Border x:Name="ValidationErrorElement" BorderThickness="1" CornerRadius="0" BorderBrush="{StaticResource ValidationBrush_Error}" Visibility="Collapsed">
                    <Grid>
                      <Popup x:Name="validationPopup"
                               AllowsTransparency="True"
                               PopupAnimation="None"
                               Placement="Bottom"
                               PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
                               DataContext="{Binding ElementName=pi}"
                               VerticalOffset="-25">
                        <Grid x:Name="Root" Margin="0" Opacity="0">
                          <Border x:Name="validationPopupBorder" Background="{StaticResource ValidationBrush_Error}" CornerRadius="0"/>
                          <Border CornerRadius="0">
                            <TextBlock x:Name="validationPopupText"
                                         UseLayoutRounding="false"
                                         Foreground="White"
                                         FontSize="11"
                                         Margin="8,4,8,4"
                                         MaxWidth="250"
                                         TextWrapping="Wrap"
                                         Text="{Binding Path=RuleDescription}" />
                          </Border>
                        </Grid>
                      </Popup>
                      <Grid Width="12" Height="12" HorizontalAlignment="Right" Margin="1,-4,-4,0" VerticalAlignment="Top" Background="Transparent">
                        <Path Margin="1,3,0,0" Data="M 1,0 L6,0 A 2,2 90 0 1 8,2 L8,7 z" x:Name="ValidationErrorElement_Path" Fill="{StaticResource ValidationBrush_Error}"/>
                        <Path Margin="1,3,0,0" Data="M 0,0 L2,0 L 8,6 L8,8" Fill="#ffffff"/>
                      </Grid>
                    </Grid>
                  </Border>
                  <Rectangle x:Name="BusyElement" Fill="#FF7A7A7A" HorizontalAlignment="Right" Width="12" Height="12" VerticalAlignment="Center" Margin="5,5,10,5" Opacity="0"/>

                  <csla:PropertyInfo Property="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Text}" x:Name="pi">
                    <i:Interaction.Triggers>
                      <ei:DataTrigger Binding="{Binding Path=RuleSeverity, ElementName=pi}">
                        <ei:DataTrigger.Value>
                          <cslaRules:RuleSeverity>Error</cslaRules:RuleSeverity>
                        </ei:DataTrigger.Value>
                        <ei:ChangePropertyAction TargetName="validationPopupText"
                                                 PropertyName="Foreground"
                                                 Value="White" />
                        <ei:ChangePropertyAction TargetName="validationPopupBorder"
                                                 PropertyName="Background"
                                                 Value="{StaticResource ValidationBrush_Error}" />
                        <ei:ChangePropertyAction TargetName="ValidationErrorElement"
                                                 PropertyName="BorderBrush"
                                                 Value="{StaticResource ValidationBrush_Error}" />
                        <ei:ChangePropertyAction TargetName="ValidationErrorElement_Path"
                                                 PropertyName="Fill"
                                                 Value="{StaticResource ValidationBrush_Error}" />
                      </ei:DataTrigger>

                      <ei:DataTrigger Binding="{Binding Path=RuleSeverity, ElementName=pi}">
                        <ei:DataTrigger.Value>
                          <cslaRules:RuleSeverity>Warning</cslaRules:RuleSeverity>
                        </ei:DataTrigger.Value>
                        <ei:ChangePropertyAction TargetName="validationPopupText"
                                                 PropertyName="Foreground"
                                                 Value="Black" />
                        <ei:ChangePropertyAction TargetName="validationPopupBorder"
                                                 PropertyName="Background"
                                                 Value="{StaticResource ValidationBrush_Warning}" />
                        <ei:ChangePropertyAction TargetName="ValidationErrorElement"
                                                 PropertyName="BorderBrush"
                                                 Value="{StaticResource ValidationBrush_Warning}" />
                        <ei:ChangePropertyAction TargetName="ValidationErrorElement_Path"
                                                 PropertyName="Fill"
                                                 Value="{StaticResource ValidationBrush_Warning}" />
                      </ei:DataTrigger>

                      <ei:DataTrigger Binding="{Binding Path=RuleSeverity, ElementName=pi}">
                        <ei:DataTrigger.Value>
                          <cslaRules:RuleSeverity>Information</cslaRules:RuleSeverity>
                        </ei:DataTrigger.Value>
                        <ei:ChangePropertyAction TargetName="validationPopupText"
                                                 PropertyName="Foreground"
                                                 Value="White" />
                        <ei:ChangePropertyAction TargetName="validationPopupBorder"
                                                 PropertyName="Background"
                                                 Value="{StaticResource ValidationBrush_Info}" />
                        <ei:ChangePropertyAction TargetName="ValidationErrorElement"
                                                 PropertyName="BorderBrush"
                                                 Value="{StaticResource ValidationBrush_Info}" />
                        <ei:ChangePropertyAction TargetName="ValidationErrorElement_Path"
                                                 PropertyName="Fill"
                                                 Value="{StaticResource ValidationBrush_Info}" />
                      </ei:DataTrigger>

                      <i:EventTrigger SourceObject="{Binding RelativeSource={RelativeSource TemplatedParent}}" EventName="GotFocus">
                        <i:Interaction.Behaviors>
                          <ei:ConditionBehavior>
                            <ei:ConditionalExpression>
                              <ei:ComparisonCondition LeftOperand="{Binding IsValid, ElementName=pi}" RightOperand="False"/>
                            </ei:ConditionalExpression>
                          </ei:ConditionBehavior>
                        </i:Interaction.Behaviors>
                        <ei:GoToStateAction StateName="CslaInvalidFocused"/>
                      </i:EventTrigger>
                      <i:EventTrigger SourceObject="{Binding RelativeSource={RelativeSource TemplatedParent}}" EventName="LostFocus">
                        <i:Interaction.Behaviors>
                          <ei:ConditionBehavior>
                            <ei:ConditionalExpression>
                              <ei:ComparisonCondition LeftOperand="{Binding IsValid, ElementName=pi}" RightOperand="False"/>
                            </ei:ConditionalExpression>
                          </ei:ConditionBehavior>
                        </i:Interaction.Behaviors>
                        <ei:GoToStateAction StateName="CslaInvalidUnfocused"/>
                      </i:EventTrigger>
                      <ei:DataTrigger Binding="{Binding IsValid, ElementName=pi}" Value="False">
                        <ei:GoToStateAction StateName="CslaInvalidUnfocused"/>
                      </ei:DataTrigger>
                      <ei:DataTrigger Binding="{Binding IsValid, ElementName=pi}" Value="True">
                        <ei:GoToStateAction StateName="CslaValid"/>
                      </ei:DataTrigger>

                      <ei:DataTrigger Binding="{Binding IsBusy, ElementName=pi}" Value="True">
                        <ei:GoToStateAction StateName="Busy"/>
                      </ei:DataTrigger>
                      <ei:DataTrigger Binding="{Binding IsBusy, ElementName=pi}" Value="False">
                        <ei:GoToStateAction StateName="Idle"/>
                      </ei:DataTrigger>

                      <ei:DataTrigger Binding="{Binding CanRead, ElementName=pi}" Value="False">
                        <ei:ChangePropertyAction TargetObject="{Binding RelativeSource={RelativeSource TemplatedParent}}"
                                                   PropertyName="Visibility" Value="Collapsed" />
                      </ei:DataTrigger>
                      <ei:DataTrigger Binding="{Binding CanWrite, ElementName=pi}" Value="False">
                        <ei:ChangePropertyAction TargetObject="{Binding RelativeSource={RelativeSource TemplatedParent}}"
                                                   PropertyName="IsReadOnly" Value="True" />
                      </ei:DataTrigger>
                    </i:Interaction.Triggers>
                  </csla:PropertyInfo>

                </Grid>

                <ControlTemplate.Triggers>
                  <DataTrigger Binding="{Binding ElementName=validationPopup, Path=IsOpen}" Value="True">
                    <DataTrigger.EnterActions>
                      <BeginStoryboard>
                        <Storyboard>
                          <DoubleAnimation Storyboard.TargetName="validationPopup" Storyboard.TargetProperty="VerticalOffset" To="0" Duration="0:0:0.2">
                            <DoubleAnimation.EasingFunction>
                              <BackEase Amplitude=".3" EasingMode="EaseOut"/>
                            </DoubleAnimation.EasingFunction>
                          </DoubleAnimation>
                          <DoubleAnimation Storyboard.TargetName="Root" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.2"/>
                        </Storyboard>
                      </BeginStoryboard>
                    </DataTrigger.EnterActions>
                    <DataTrigger.ExitActions>
                      <BeginStoryboard>
                        <Storyboard>
                          <DoubleAnimation Storyboard.TargetName="validationPopup" Storyboard.TargetProperty="VerticalOffset" To="-25" Duration="0:0:0.2">
                            <DoubleAnimation.EasingFunction>
                              <BackEase Amplitude=".3" EasingMode="EaseOut"/>
                            </DoubleAnimation.EasingFunction>
                          </DoubleAnimation>
                          <DoubleAnimation Storyboard.TargetName="Root" Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.2"/>
                        </Storyboard>
                      </BeginStoryboard>
                    </DataTrigger.ExitActions>
                  </DataTrigger>
                </ControlTemplate.Triggers>
              </ControlTemplate>         
          </Setter.Value>
        </Setter>
    </Style> 

    Page 1 of 1 (5 items) | RSS

    Copyright (c) 2006-2014 Marimer LLC. All rights reserved.
    Email admin@lhotka.net for support.
    Powered by Community Server (Non-Commercial Edition), by Telligent Systems