2 Stimmen

WPF Umgekehrte Bindung OneWayToSource

Ich habe ein benutzerdefiniertes Steuerelement, das die folgende Abhängigkeitseigenschaft hat

public static readonly DependencyProperty PrintCommandProperty = DependencyProperty.Register(
      "PrintCommand",
      typeof(ICommand),
      typeof(ExportPrintGridControl),
      new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits));

public ICommand PrintCommand
{
    get { return (ICommand)GetValue(PrintCommandProperty); }
    set { throw new Exception("ReadOnly Dependency Property. Use Mode=OneWayToSource"); }
}

im Konstruktor meines Steuerelements setze ich den Standardwert meiner Eigenschaft:

public MyControl()
{
   this.SetValue(PrintCommandProperty, new DelegateCommand<object>(this.Print));
}

Ich versuche dann, die Eigenschaft an mein ViewModel zu binden, so dass ich auf die Eigenschaft zugreifen und den Druckbefehl aufrufen kann.

<controls:MyControl PrintCommand="{Binding PrintCommand, Mode=OneWayToSource}"/>

Die Bindung in der XAML bewirkt jedoch, dass der Eigenschaftswert auf Null gesetzt wird. Wenn ich die Bindung in XAML entfernen, wird der Standard-Eigenschaftswert richtig im Konstruktor meines Steuerelements festgelegt.

Was ist der richtige Weg, um mein ViewModel die Print-Methode meines Steuerelements aufzurufen?

0voto

Ray Burns Punkte 60870

Ich habe gerade Ihre Frage erneut gelesen, und es klingt wie Sie versuchen, eine Methode in Ihrer Ansicht von Ihrem Ansichtsmodell aufrufen. Dafür ist ein Ansichtsmodell nicht gedacht.

Wenn dies wirklich das ist, was Sie wollen, brauchen Sie keinen Befehl zu verwenden: Ihre Ansicht braucht nur aufzurufen:

view.Print()

Wenn Sie den Druckbefehl ändern wollen, brauchen Sie eine Eigenschaft wie gezeigt. In diesem Fall würde Ihr Ansichtsmodell Folgendes aufrufen

view.PrintCommand.Execute()

In keinem der beiden Fälle ist eine Datenbindung erwünscht.

Eine mehr WPF-ish Weg, dies zu tun ist, um eine Bindung an Ihr Steuerelement der hinzufügen CommandBindings Sammlung zur Handhabung der eingebauten Application.Print Befehl. Dann kann das View Model diesen Befehl mit RaiseEvent wenn es drucken will.

Beachten Sie, dass ein CommandBinding ein völlig anderes Objekt ist als ein Binding. Verwechseln Sie die beiden nicht. Ein CommandBinding wird für die Verarbeitung von gerouteten Befehlen verwendet. Ein Binding wird zum Aktualisieren von Eigenschaftswerten verwendet.

0voto

John Bowen Punkte 23673

Die Art und Weise, wie Sie die Befehlsbindung verwenden, weicht von der normalen Art und Weise ab, wie sie in MVVM verwendet wird. Normalerweise deklarieren Sie eine DelegateCommand in Ihrer VM, die eine Aktion in der VM auf der Grundlage einer UI-Aktion (z. B. Klicken auf eine Schaltfläche) ausführen würde. Da Sie den umgekehrten Weg suchen, wäre es wahrscheinlich besser, ein Ereignis zu verwenden, das von Ihrer VM ausgeht und dann von der ExportPrintGridControl . Je nachdem, wie die Beziehungen aufgebaut sind, können Sie den Event-Handler in XAML auf der VM-Instanz-Deklaration deklarieren (sieht in Ihrem Fall nicht so aus) oder in Ihrem Steuercode einfach die DataContext und übergeben es an Ihre VM oder (besser) an eine Schnittstelle, die das zu abonnierende Ereignis enthält.

p.s. Ihr DependencyProperty ist derzeit so eingerichtet, dass alles, was außerhalb Ihrer Klasse liegt, es durch den Aufruf von SetValue (wie bei allen XAML-Programmen). Ich verstehe, warum Sie es auf diese Weise eingerichtet hatten, um zu versuchen, es als Push-only Binding zu verwenden, aber hier ist eine bessere Implementierung von Read-only für Situationen, wenn Sie wirklich brauchen, dass:

private static readonly DependencyPropertyKey PrintCommandPropertyKey = DependencyProperty.RegisterReadOnly(
  "PrintCommand",
  typeof(ICommand),
  typeof(ExportPrintGridControl),
  new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits));

public static readonly DependencyProperty PrintCommandProperty = PrintCommandPropertyKey.DependencyProperty;

public ICommand PrintCommand
{
    get { return (ICommand)GetValue(PrintCommandProperty); }
    private set { SetValue(PrintCommandPropertyKey, value); }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X