2010-03-02 3 views
2

У меня есть пользовательский элемент управления, который имеет свойствоWPF Reverse Binding OneWayToSource

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

следующую зависимость в конструкторе моего контроля я устанавливаю значение по умолчанию моей собственности:

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

Я затем пытается связать свойство с моей ViewModel, чтобы я мог получить доступ к свойству и вызвать команду печати.

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

Однако привязка в XAML приводит к тому, что значение свойства будет установлено равным нулю. Если я удалю привязку в XAML, значение свойства по умолчанию будет правильно установлено в конструкторе моего элемента управления.

Каков правильный способ заставить мою модель ViewModel вызвать метод печати моего элемента управления?

ответ

0

Я просто перечитал ваш вопрос, и похоже, вы пытаетесь вызвать метод в своем представлении из своей модели просмотра. Это не то, для чего предназначена модель представления.

Если это действительно то, что вы хотите, нет необходимости использовать команду: Все ваше мнение нужно сделать, это вызов:

view.Print() 

Если вы хотите изменить команду печати, то вы хотите как показано. В таком случае ваша модель будет называться

view.PrintCommand.Execute() 

В любом из этих случаев вы не нуждаетесь в привязке данных.

Более WPF-ish способ сделать это - добавить привязку к коллекции вашего управления CommandBindings для обработки встроенной команды Application.Print. Тогда модель просмотра может отправить эту команду с помощью RaiseEvent, когда она захочет распечатать.

Обратите внимание, что CommandBinding - это совершенно другой объект, чем привязка. Не путайте их. CommandBinding используется для обработки маршрутизируемых команд. Связывание используется для обновления значений свойств.

0

Способ, которым вы используете привязку команд, находится назад от обычного способа использования в MVVM. Обычно вы намотали объявление DelegateCommand на вашей виртуальной машине, которое будет предпринимать некоторые действия в виртуальной машине на основе действия пользовательского интерфейса (например, нажатие кнопки). Поскольку вы ищете противоположный путь, вам, вероятно, будет лучше использовать событие, происходящее из вашей виртуальной машины, которое затем может обрабатываться ExportPrintGridControl. В зависимости от того, как настроены отношения, вы можете объявить обработчик событий в XAML в объявлении экземпляра VM (не похоже на него в вашем случае), или в вашем контрольном коде просто возьмите DataContext и отпустите его на свою виртуальную машину или (лучше) интерфейс, который включает событие для подписки.

p.s. Ваш DependencyProperty настроен таким образом, чтобы все, что было нарушено вашим классом, могло установить его, вызвав SetValue (как и все XAML). Я понимаю, почему вы настроили этот способ, чтобы попытаться использовать его как привязку только для push, но здесь лучше реализовать только чтение для ситуаций, когда вам это действительно нужно:

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); } 
} 
Смежные вопросы