Хорошо, это быстрый и грязный, но многоразовый класс поведения. Отказ от ответственности: я просто взломал это через пару минут, и у него есть свои недостатки, которые легко преодолеть.
Для начала нужен наш класс обслуживания.
public class VisualPrinter
{
private static RoutedUICommand PrintVisualCommand = new RoutedUICommand("PrintVisualCommand", "PrintVisualCommand", typeof(VisualPrinter));
#region ab PrintCommand
public static ICommand GetPrintCommand(DependencyObject aTarget)
{
return (ICommand)aTarget.GetValue(PrintCommandProperty);
}
public static void SetPrintCommand(DependencyObject aTarget, ICommand aValue)
{
aTarget.SetValue(PrintCommandProperty, aValue);
}
public static readonly DependencyProperty PrintCommandProperty =
DependencyProperty.RegisterAttached("PrintCommand", typeof(ICommand), typeof(VisualPrinter), new FrameworkPropertyMetadata(PrintVisualCommand));
#endregion
#region ab EnablePrintCommand
public static bool GetEnablePrintCommand(DependencyObject aTarget)
{
return (bool)aTarget.GetValue(EnablePrintCommandProperty);
}
public static void SetEnablePrintCommand(DependencyObject aTarget, bool aValue)
{
aTarget.SetValue(EnablePrintCommandProperty, aValue);
}
public static readonly DependencyProperty EnablePrintCommandProperty =
DependencyProperty.RegisterAttached("EnablePrintCommand", typeof(bool), typeof(VisualPrinter), new FrameworkPropertyMetadata(false, OnEnablePrintCommandChanged));
private static void OnEnablePrintCommandChanged(DependencyObject aDependencyObject, DependencyPropertyChangedEventArgs aArgs)
{
var newValue = (bool)aArgs.NewValue;
var element = aDependencyObject as UIElement;
if(newValue)
{
element.CommandBindings.Add(new CommandBinding(PrintVisualCommand, OnPrintVisual));
}
}
private static void OnPrintVisual(object aSender, ExecutedRoutedEventArgs aE)
{
// the element is the one were you set the EnablePrintCommand
var element = aSender as Visual;
var printDlg = new PrintDialog();
// do the printing
}
#endregion
}
Здесь мы определяем два прикрепленных свойства. PrintCommand
используется для ввода фактической команды печати в модель просмотра, это должно выполняться с помощью OneWayToSource. Второй, EnablePrintCommand
, должен включить печать, установить, какой элемент должен быть напечатан, и зарегистрировать привязку команды.
В моей текущей версии есть недостаток, что вы не можете установить оба свойства на один и тот же элемент, но это легко преодолеть. Таким образом, чтобы напечатать на кнопку, она будет выглядеть следующим образом:
<Grid local:VisualPrinter.EnablePrintCommand="True">
<Button Content="Test" local:VisualPrinter.PrintCommand="{Binding ViewModelPrint, Mode=OneWayToSource">
</Grid>
Хотя ViewModelPrint
является свойством типа ICommand в модели представления, которая может быть выполнена и затем напечатать сетку (поэтому кнопка).
Почему вы хотите, чтобы ваш ViewModel знал о вашем представлении, если вы используете MVVM? – Dutts
Почему вы не хотите использовать команду? Ну, вы всегда можете привязать представление к свойству в своей модели просмотра. Я бы с удовольствием использовал приложенное поведение для этого. Присвоение команде вложенного свойства, в элементе, привязать команду OneWayToSource к модели представления, запустить ее там и обработать ее самим элементом управления через прикрепленное поведение. – dowhilefor
Я хочу распечатать документ/окно после того, как произошло какое-то событие. Так что печать не вызывается с помощью RelayCommand, а событие/условие происходит в коде..Не на view/xaml –