We are looking at creating a helper class for validation on a DevExpress WPF application single view model.
In our xaml, we want to add a reference to our ValidationServiceHelper class:
<dxlc:DataLayoutControl x:Name="layoutControlMyObject" Style="{StaticResource EntityView.DataLayoutControl}"
viewmodel:ValidationServiceHelper.HasErrors="{Binding RelativeSource={RelativeSource Self}, Path=(dxe:ValidationService.HasValidationError)}">
The ValidationServiceHelper class looks like this:
namespace MyApplication.ViewModels
{
public partial class MyObjectViewModel :
SingleObjectViewModel<MyObject, int, IMyEntityUnitOfWork>
{
// ...
}
public class ValidationServiceHelper
{
public static bool GetHasErrors(DependencyObject obj)
{
return (bool)obj.GetValue(HasErrorsProperty);
}
public static void SetHasErrors(DependencyObject obj, bool value)
{
obj.SetValue(HasErrorsProperty, value);
}
public static readonly DependencyProperty HasErrorsProperty =
DependencyProperty.RegisterAttached("HasErrors", typeof(bool),
typeof(ValidationServiceHelper), new PropertyMetadata(false, OnHasErrorsChanged));
private static void OnHasErrorsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
try
{
FrameworkElement element = (FrameworkElement)d;
element.Dispatcher.BeginInvoke(new Action(() =>
((MyObjectViewModel)element.DataContext).ViewHasErrors = (bool)e.NewValue));
var err = ValidationService.GetValidationErrors(d);
if (err != null)
element.Dispatcher.BeginInvoke(new Action(() =>
((MyObjectViewModel)element.DataContext).ViewErrors =
err.Select(p => p.ErrorContent).Distinct().Aggregate(
(j, i) => string.Format("{0}{1}{2}", i, Environment.NewLine, j)).ToString()));
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
}
}
Looking at the two Dispatcher.BeginInvoke calls in OnHasErrorsChanged, you will see I hard-coded a cast to MyObjectViewModel.
element.Dispatcher.BeginInvoke(new Action(() =>
((MyObjectViewModel)element.DataContext).ViewHasErrors = (bool)e.NewValue));
Written like this, I would need to create a different helper class. Is there a way to make this generic, so I can only use one class for all my view models?
You could derive your view model classes from a common base class (or implement an interface) where the
ViewErrors
property is defined and cast to this type:But you will never be able to cast the
DataContext
to any other type than the actual type of the object in memory. Using generics one way or another doesn't change this fact.And there is no way to cast a
SingleObjectViewModel<A, int, IMyEntityUnitOfWork>
to aSingleObjectViewModel<B, int, IMyEntityUnitOfWork>
because these are two totally different types.