2017-09-12 1 views
-1

Wir versuchen, eine Hilfsklasse für die Validierung in einem Einzelansichtsmodell der DevExpress WPF-Anwendung zu erstellen.Verwenden von Generics für Klassen mit der statischen DependencyProperty

In unserer XAML wollen wir einen Verweis auf unsere ValidationServiceHelper Klasse hinzuzufügen:

<dxlc:DataLayoutControl x:Name="layoutControlMyObject" Style="{StaticResource EntityView.DataLayoutControl}" 
    viewmodel:ValidationServiceHelper.HasErrors="{Binding RelativeSource={RelativeSource Self}, Path=(dxe:ValidationService.HasValidationError)}"> 

Die ValidationServiceHelper Klasse sieht wie folgt aus:

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); 
      } 
     } 
    } 
} 

an den beiden suchen Dispatcher.BeginInvoke in OnHasErrorsChanged ruft Sie sehen, dass ich eine Umwandlung in MyObjectViewModel fest codiert habe.

element.Dispatcher.BeginInvoke(new Action(() => 
    ((MyObjectViewModel)element.DataContext).ViewHasErrors = (bool)e.NewValue)); 

So geschrieben, ich müsste eine andere Helferklasse erstellen. Gibt es eine Möglichkeit, dies generisch zu machen, sodass ich nur eine Klasse für alle meine Ansichtsmodelle verwenden kann?

Antwort

0

Sie könnten Ihre Ansicht Modellklassen von einer gemeinsamen Basisklasse ableiten (oder eine Schnittstelle implementieren), wo die ViewErrors Eigenschaft definiert ist und gegossen zu dieser Art:

var vm = element.DataContext as BaseViewModel; 
if (vm != null) 
    element.Dispatcher.BeginInvoke(new Action(() => vm.ViewHasErrors = (bool)e.NewValue)); 

Aber Sie werden nie die werfen können, DataContext zu einem anderen Typ als dem tatsächlichen Typ des Objekts im Speicher. Die Verwendung von Generika auf die eine oder andere Weise ändert diese Tatsache nicht.

Und es gibt keine Möglichkeit, eine SingleObjectViewModel<A, int, IMyEntityUnitOfWork> zu einer SingleObjectViewModel<B, int, IMyEntityUnitOfWork> zu werfen, weil dies zwei völlig unterschiedliche Typen sind.

+0

Ich glaube, ViewErrors ist Teil der Basisklasse, SingleObjectViewModel; Diese Klasse benötigt jedoch drei Typargumente, die verwendet werden, um anzugeben, welches EF-Modell sie verwendet. – Pizzor2000

+0

Verschieben Sie die Eigenschaft in eine nicht generische Basisklasse des generischen Objekts, oder implementieren Sie eine Schnittstelle, und konvertieren Sie sie in dieses. – mm8

+0

Wie bereits erwähnt, gibt es keine Möglichkeit, ein SingleObjectViewModel in ein SingleObjectViewModel zu konvertieren, da es sich um zwei völlig unterschiedliche Typen handelt. Es ist, als würde man versuchen, einen Int auf einen Button zu werfen und würde immer versagen. Zwei Instanzen eines generischen Typs mit unterschiedlichen Typparametern sind zwei völlig unterschiedliche Typen. Die generische Definition selbst ist * nicht * irgendeine Art von Basisklasse für alle generischen Typen. – mm8

Verwandte Themen