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.RuleArgs) As 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.
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
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?
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
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.
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