This thread looks to be a little on the old side and therefore may no longer be relevant. Please see if there is a newer thread on the subject and ensure you're using the most recent build of any software if your question regards a particular product.
This thread has been locked and is no longer accepting new posts, if you have a question regarding this topic please email us at support@mindscape.co.nz
|
We're using the v2 property grid with objects that implement IDataErrorInfo. One limitation we're hitting is that we want different visuals for errors of different severity (we have our own validation mechanism that is accessed via IDataErrorInfo). For example, an error could have the default red border in the property grid. A warning or lower priority error, on the other hand, might have a yellow border. Does the property grid have a built in mechanism to support different error severities? I realize that IDataErrorInfo may be too limiting; is there a different supported interface that would allow severity to be automatically displayed in the grid? Thanks, -Craig |
|
|
There is no standard mechanism for this in the grid because there is no standard mechanism for error severity in the .NET rich client data binding infrastructure (as far as we know). One possibility is to create custom validation rules which in turn return custom validation results -- extending the ValidationResult type to include a severity level. There are however two issues with this: 1. You would need to recreate the built-in editors in order to re-specify the data bindings and invoke your custom validation rules. This is a bit tedious and creates potential maintenance issues. 2. The binding is not to the "real" object, but to a proxy object of type ObjectWrapper. So, for example, you cannot query for a custom interface, because ObjectWrapper will not implement that interface. If your validation mechanism tunnels over IDataErrorInfo, e.g. by returning an XML string containing a severity and error text, then this isn't an issue (because ObjectWrapper proxies IDataErrorInfo faithfully). Otherwise, you can get at the real object via ObjectWrapper.UnderlyingObject; but this may not be possible from within a ValidationRule because Validate gives you only the value to validate, not the binding source (the ObjectWrapper). (DataErrorValidationRule seems to get some special handling to work around this, but I don't know if user validation rules can hook into that.) Another possible approach is to bypass the WPF binding validation infrastructure altogether and implement error display as a separate visual item in your editors. This would then have direct access to the real object -- and its custom error reporting mechanisms -- via UnderlyingObject. However some thought would be required around how to signal a change in the error state, and how to retrieve that error state for the specific property being edited. Hope this helps -- we would be happy to provide more advice or suggestions if you have specific constraints or design ideas. |
|
|
First off, thanks very much for the great info. above. I needed to solve this same problem for a datagrid we use and ended up taking the approach of bypassing validation altogether. I was hoping to use a similar approach for the property grid; I've pasted a XAML sample below to make discussing it easier:< ms:BuiltInEditorStyle EditorKey="{x:Static ms:PropertyGrid.SimpleTextEditorKey}" > <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}"> <Style.Triggers> <DataTrigger Value="Warning"> <DataTrigger.Binding><MultiBinding Converter="{StaticResource validityConverter}" ConverterParameter="" ><Binding Path="UnderlyingObject" Mode="OneWay" /><Binding Path="PropertyName" UpdateSourceTrigger="PropertyChanged" /> </MultiBinding> </DataTrigger.Binding><Setter Property="TextBox.BorderBrush" Value="{DynamicResource warningBrush}" /><Setter Property="TextBox.BorderThickness" Value="10" /> </DataTrigger></Style.Triggers> </Style> </ms:BuiltInEditorStyle>Here, I'm altering the built in text editor's style so it's based on my project's textbox theme. Additionally, I'm using a trigger to change the border brush and thickness of the textbox depending on severity. The trigger uses a multibinding, which has the underlying object as one binding and the property of interest as the second binding. The notion is that when the property changes, that should trigger the multibinding to re-evaluate, at which time the object and property are passed into the converter. The converter uses the object's IDataErrorInfo fields to determine if an error exists and, if so, its severity. When trying this with the property grid, it unfortunately didn't work. I'm not certain if I'm conflicting with the style's built in use of error validation. Alternatively, I imagine that binding to the object wrapper's "PropertyName" isn't correct. The reason I tried that is that I'd like the style to apply to all properties so I was hoping "PropertyName" would equate to the "property tied to this editor instance" in XAML. Note that I also tried setting the binding's Path to a specific property: "UnderlyingObject.Length" and another generic approach: "Property.Value" but neither fixed the problem. I guess I could use a property editor but that seems wasteful since I want the same error behavior for all the properties. If there's a way to perform the style change within the editor styles, can I make it apply to all the editor styles in one block instead of needing to apply it to each style (CheckBoxEditor, TextBoxEditor, etc...) ? Also, as a side question, is there a way for me to specify BuiltInEditorStyles as a resource so I can apply my style changes across multiple property grids without having to copy/paste the same XAML? Any additional advice or suggestions you have on the above approach are greatly appreciated. Thanks, -Craig |
|
|
Hello Craig, I think the problem is that nothing is going to cause your MultiBinding to update. The two things you have in the MultiBinding are: - UnderlyingObject, which is a reference to the object whose property is being edited. Although that object's properties are changing, the object *reference* (the identity) is not. - PropertyName, which is the name of the property being edited. Obviously this won't change when the value changes. So what I would suggest (and be warned I haven't tested this) is adding a third element to the MultiBinding. This would be the Value itself. (Don't use Property.Value, because Property refers to the underlying Node, which doesn't raise PropertyChanged notifications for its Value property. I know the naming and behaviour are confusing here; sorry.) So the MultiBinding would look something like: <MultiBinding Converter="{StaticResource validityConverter}"> Now when the user edits the value, this will raise a PropertyChanged notification which via the ObjectWrapper.Value will reach the MultiBinding and cause it to update. Regarding your other questions: I can't think of a way to make a style change apply to all the editor styles in one go; sorry. Yes, you should be able to specify a BuiltInEditorStyle as a resource. Moreover, you can create a Style resource for the grid itself, which can contain all your BuiltInEditorStyles. See the 2.0 visual styles (in Source\Styles) for examples. |
|
|
Using "Value" does seem to do the trick for get the binding to re-evaluate. However, I'm still seeing the red border for the standard validation visual; as opposed to my yellow border I defined via the data trigger setters. I know the converter is being hit (via bp's and print's). Is there a way for me to debug the style itself, to see if maybe my setter's are ignored due to the built in validation visuals being triggered? Thanks, -Craig |
|
|
Debugging WPF styles is never easy, and we don't have any specific facilities to help in the case of the grid. What may be happening is that your yellow border is showing but being hidden by the red border, because you have . I'd suggest checking out tools such as Snoop and Mole; or for a more "printf debugging" technique I sometimes just stick a Big Obvious Element like a 100-pixel red square in my style/template to make sure that it shows up (the style is being applied), changes colour when appropriate (triggers are behaving), etc. If it is the default red border overwriting your yellow one then the quickest fix is probably to create your own validation error template which is empty / transparent. |
|
|
I ended up overwriting the Validation.ErrorTemplate property within the DataTrigger, which is working great. Thanks again, -Craig |
|