Laden...

Command in CodeBehind ohne Assembly-Referenz

Erstellt von Uwe81 vor 9 Jahren Letzter Beitrag vor 9 Jahren 1.655 Views
U
Uwe81 Themenstarter:in
282 Beiträge seit 2008
vor 9 Jahren
Command in CodeBehind ohne Assembly-Referenz

Hallo!

Ich programmiere gerade ein WPF UserControl, welches in einer fremden Anwendung eingebunden werden soll.

Aus den Anforderungen der Anwendung hat sich folgende Architektur ergeben:
Ein Assembly, welches die BL und das ViewModel beinhaltet.
Ein Assembly, welches das Control beinhaltet.
(ich weiß, dass man BL und ViewModel lieber trennen würde, da aber beides aus 3 bis 6 kleinen Klassen besteht, tut mir das nicht wirklich weh).

Für die Anwendung ist es vorteilhaft, dass die beiden Assemblies sich nicht referenzieren. Soweit funktioniert das auch alles gut.

Das Problem ist nun folgendes:
Mein Control muss ein interface implementieren, welches (z.B.) so aussieht:


interface IApplicationControl {
  public void OnCanExecute(CanExecuteRoutedEventArgs e) { }
  public void OnExecuted(ExecutedRoutedEventArgs e) { }
}

In den EventArgs steht dann jeweils über die OriginalSource der Name des Buttons.

Jetzt würde ich gerne an dieser Stelle quasi ein Command aus dem ViewModel fragen nach CanExecute bzw. in die Execute aufrufen. Also


class MyViewModel {
  public ICommand OkCommand {get; private set;}
}

class MyControl : IApplicationControl {
  public void OnCanExecute(CanExecuteRoutedEventArgs e) { 
    
    if (e.OriginalSource.Name == "Ok"){
        MyViewModel viewModel = DataContext as MyViewModel; //GEHT NICHT!!
        e.CanExecute = viewModel.OkCommand.CanExecute(null);
    }
  }
}

Aber ich kann den DataContext ja nicht auf das spezifische ViewModel casten, weil ich keine Referenz auf das Assembly habe.

Gibt es nun einen "eleganten" Weg, dass ich mir in XAML dieses Command über DataBinding hole, oder muss ich das im CodeBehind über Reflection machen?

Vielen Dank!

4.939 Beiträge seit 2008
vor 9 Jahren

Hallo,

also View und ViewModel zu trennen, ist, wie du jetzt siehst, keine so gute Idee - besser ist es die BL (über ein Interface) wegzukapseln.
Egal wie, aber du solltest eine dritte Assembly erzeugen, welche nur die Interfaces beinhaltet (d.h. in deinem Fall jetzt für das MyViewModel ein IMyViewModel anbieten).

U
Uwe81 Themenstarter:in
282 Beiträge seit 2008
vor 9 Jahren

Wenn ich die Anwendung selbst in der Hand hätte, würde ich die Assembly-Aufteilung auch nicht so machen.

So ist es aber, dass die Anwendung meinen Code per COM-Schnittstelle aufruft, ich dann meinerseits eine Methode aufrufe, die mein Control erzeugt und in einem vorgegebenen Rahmen anzeigt. Dabei müssen die Assemblies aber an unterschiedlichen Stellen liegen, insbesondere das Control in einem bestimmten Unterordner des Programms.

Jetzt habe ich es erstmal so gelöst, dass ich mir per Reflection das Command als ICommand hole.

Sollten noch weitere Abhängigkeiten entstehen, muss ich das nochmals überdenken. Allerdings weiß ich garnicht so genau, wo dann das gemeinsam bekannte Interface-Assembly liegen soll. Im Ordner der View? Im Ordner der Logik (die per COM-Interface angestoßen wird).

74 Beiträge seit 2014
vor 9 Jahren

Du könntest deiner MyControl-Klasse eine DependencyProperty vom Typ ICommand geben, daran das Command aus dem VM binden und dann in deiner OnCanExecute-Methode mit der DependencyProperty arbeiten. Das gleiche machen doch im Prinzip auch die ICommandSource-Klassen in WPF.