XAML Conditionally required Business Rules + UI warnings

XAML Conditionally required Business Rules + UI warnings

Old forum URL: forums.lhotka.net/forums/t/11320.aspx


jamie.clayton posted on Sunday, April 22, 2012

G'day,

I'm having a senior moment with XAML and CSLA business rules displaying optionally required fields in WPF at the moment. Can someone please put me out of my misery?

I have a simple business Rule like like the following, so if a user selected the report format should be PDF, there is a conditional requirement to also supply the file path and name of file for that report.

Private Shared Function PdfFilePathSuppliedRule(Of T As ReportDataFilter)
(ByVal target As T, ByVal e As Validation.RuleArgsAs Boolean     Dim result As Boolean = True     If target.IsOutputToPDF Then         If String.IsNullOrWhiteSpace(target.PdfFilePath) Then             result = False             e.Description = "Must supply a location and file name 
for the PDF report output."
        End If     End If     Return result End Function

So the XAML UI should, in my mind do the following.

  1. User Clickes on Checkbox - Output to PDF.
  2. PDF file path text box should now highlight as a required field, with the standard red boarder.
  3. User see's red and supplies file path.
  4. Report can be generated.

So I apply this logic and ensure that the property change also triggers the business rules to run from both properties and they are implicitly related via this business rule. The UI just never updates the conditionally required text box when the check box property changes. All the events fire as expected when I debug through this code. It looks like the UI warnings only change if the matching property changes.

I then start to review what's going on in the CSLA core code for Csla.Wpf.PropertyStatus in (3.8.4). It implies the only way you can force the second property to display the broken rule to the user is to

  1. Force a change in the value of the PdfFilePath property and then instantly undo it.
  2. Disconnect and then reconnect the XAML framework object to the CSLA BO property.

This all sounds a little complicated, or my reading of C# might be incorrect, usually indicating I've stuffed up somewhere.  Is there a CSLA method call I've missed, that can help me resolve this UI business rule issue in WPF?

jamie.clayton replied on Sunday, April 22, 2012

Did some searching in the Forum and tried a few techniques. Eventually found a solution.

''' <summary>
''' All custom rules need to be placed in this method.
''' </summary>
''' <Returns>Return true to override the generated rules If false generated rules will be run.</Returns>
Protected Function AddBusinessValidationRules() As Boolean
 
    '   We want the UI warnings for Report outputs types, to go against the file text boxes,
    '   so we are taking the step of validating against the file path fields and associating the two properties as Dependant.
 
    '   Ensure that a PDF file path is supplied if the users selects output to pdf.           
    ValidationRules.AddRule(Of ReportDataFilter, RuleArgs)(AddressOf ReportDataFilter.PdfFilePathSuppliedRule, New RuleArgs(PdfFilePathProperty))
    ValidationRules.AddDependentProperty(IsOutputToPDFProperty, PdfFilePathProperty, True)
 
    '   Ensure that a Excel file path is supplied if the users selects output to Excel.
    ValidationRules.AddRule(Of ReportDataFilter, RuleArgs)(AddressOf ReportDataFilter.ExcelFilePathSuppliedRule, New RuleArgs(ExcelFilePathProperty))
    ValidationRules.AddDependentProperty(IsOutputToExcelProperty, ExcelFilePathProperty, True)
 
    Return False
End Function
''' <summary>
''' We need to force cross checking of other properties as they are dependent properties together.
''' </summary>
''' <param name="propertyName"></param>
''' <remarks></remarks>
Protected Overrides Sub OnPropertyChanged(ByVal propertyName As String)
    MyBase.OnPropertyChanged(propertyName)
 
    '   Fake the editing of other fields.
    '   Works in combination with the ValidationRules.AddDependentProperty
    Select Case propertyName
        Case IsOutputToPDFProperty.Name
            OnPropertyChanged(PdfFilePathProperty.Name)
        Case IsOutputToExcelProperty.Name
            OnPropertyChanged(ExcelFilePathProperty.Name)
    End Select
 
End Sub

JonnyBee replied on Sunday, April 22, 2012

Hi Jamie,

You Rules is corrrect but the OnPropertyChanged override should not be required to make this work.

I suspect that your app is using "Windows" as PropertyChangedMode.

For XAML in CSLA 3.x you must set
CslaPropertyChangedMode = "Xaml"
in app.config to make your app use the XAML property changed mode.

Windows is default mode for all Csla 3.x.
Xaml
is default mode for Csla 4.x

This is the actual code in BusinessBase:

    protected virtual void PropertyHasChanged(Csla.Core.IPropertyInfo property)
    {
      MarkDirty(true);
      var propertyNames = BusinessRules.CheckRules(property);
      if (ApplicationContext.PropertyChangedMode == ApplicationContext.PropertyChangedModes.Windows)
        OnPropertyChanged(property);
      else
        foreach (var name in propertyNames)
          OnPropertyChanged(name);
    }

So when PropertyChangedMode is Windows the <BO> will only raise OnPropertyChanged for PrimaryProperty.
But when PropertyChangedMode is Xaml the <BO> will raise OnPropertyChanged for all AffectedProperties and this should do the same work as your OnPropertyChanged override.

jamie.clayton replied on Sunday, April 22, 2012

JonnyBee
For XAML in CSLA 3.x you must set
CslaPropertyChangedMode = "Xaml"
in app.config to make your app use the XAML property changed mode

Jonny,

Thanks for the information on *.config settings, I wasn't aware, or forgot about page 314 of Rockies 2008 Csla book which covers this setting. This is going to be something I will need to manage as I move from a Hybrid Windows forms and WPF solution to exclusive WPF accross our customer's software. I also removed the OnPropertyChanged code and yet again your correct about not needing it.  Will be refactoring some business objects to take advantage of this knowledge, cheers!

Copyright (c) Marimer LLC