2012-04-17 2 views
3

Я разрабатываю приложение для продажи точки, используя wpf/mvvm. В течение многих периодов жизненного цикла транзакций будут напечатаны квитанции в фоновом режиме. Я использовал другие примеры, чтобы генерировать и печатать квитанции в фоновом режиме. Я печатаю UserControl в фоновом режиме, и все выглядит великолепно.WPF MVVM фоновая печать databinding проблема

Затем я создал ViewModel для управления, чтобы он мог загрузить транзакцию для печати. Я начал с 2 основных текстовых полей - текстового заголовка «Клиентская квитанция» и верхнего заголовка «Отпечатано в: MM/dd/yy hh: mm tt».

Это как отладчик показывает жизненный цикл, когда я нажимаю кнопку печати:

  • Создает новый экземпляр элемента управления.
  • Создает новый экземпляр ViewModel
  • Устанавливает текст для свойств INPC
  • Запускает меру на контроле, чтобы получить нужный размер допечатной
  • Грузы диалоговое окно печати & извлекает очереди имена печати
  • Масштабирует размер элемента управления для соответствия квитанционной бумаге (не нужно масштабировать для моего текущего выбранного принтера, так как ширина ImageArea устанавливается так же, как и мой UC)
  • Повторно измеряет и упорядочивает сетку на основе «новой», масштабный размер изображения
  • называет PrintDialog.PrintVisual - посылающий UserControl
  • принтер выплевывает квитанцию ​​- без текста DataBound
  • Затем мои шаги отладчика в ГЭТ {вернуть _HeaderText; } часть кода - после того, как элемент управления уже напечатан.

Есть ли способ принудительно привязать данные к управлению до того, как он будет отправлен на принтер без необходимости загрузки элемента управления в панель и сделать его видимым? Я хочу иметь возможность, например, пронести по кредитной карте и распечатать квитанцию ​​с линией подписи в фоновом режиме, из небольшого всплывающего окна, которое запрашивает подробности CC (или проведите по экрану).

Есть ли лучший способ достичь этого? Метод

PrintReceipt:

ClientReceiptView control = new ClientReceiptView(Message);  
System.Windows.Controls.PrintDialog printDlg = new System.Windows.Controls.PrintDialog(); 
PrintQueue ReceiptPrinter = new LocalPrintServer().GetPrintQueue("CITIZEN CT-S310"); 
PrintCapabilities PC = ReceiptPrinter.GetPrintCapabilities(); 
printDlg.PrintQueue = ReceiptPrinter; 
control.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); 
Size PreGridSize = control.DesiredSize; 
double Scale = Math.Min(PC.PageImageableArea.ExtentWidth/PreGridSize.Width, PC.PageImageableArea.ExtentHeight/PreGridSize.Height); 
control.LayoutTransform = new System.Windows.Media.ScaleTransform(Scale, Scale); 
Size PaperSize = new Size(PC.PageImageableArea.ExtentWidth, Math.Min(PC.PageImageableArea.ExtentHeight, PreGridSize.Height)); 
control.Measure(PaperSize); 
Point ptGrid = new Point(PC.PageImageableArea.OriginWidth, PC.PageImageableArea.OriginHeight); 
control.Arrange(new Rect(ptGrid, PaperSize)); 
printDlg.PrintVisual(control, "My App"); 

И Посмотреть конструктор (с аргументами)

public ClientReceiptView(string Header) 
{ 
    InitializeComponent(); 
    vm = new ClientReceiptViewModel(Header); 
    this.DataContext = vm; 
} 

И ViewModel:

public class ClientReceiptViewModel : ViewModelBase 
{ 
    #region Properties 

    private string _HeaderText; 

    public string HeaderText 
    { 
     get { return _HeaderText; } 
     set { _HeaderText = value; OnPropertyChanged("HeaderText"); } 
    } 

    private int _TripID; 

    public int TripID 
    { 
     get { return _TripID; } 
     set { _TripID = value; OnPropertyChanged("TripID"); } 
    } 

    private string _PrintedOn; 

    public string PrintedOn 
    { 
     get { return _PrintedOn; } 
     set { _PrintedOn = value; OnPropertyChanged("PrintedOn"); } 
    } 

    #endregion 

    public ClientReceiptViewModel(string Header) 
    { 
     HeaderText = Header; 
     TripID = 2220013; 
     PrintedOn = "Printed: " + DateTime.Now.ToString("MM/dd/yy hh:mm tt"); 
    } 
} 

Edit: Call Stack от Binding/Создание с break on OnPropertyChanged ("HeaderText"):

Namespace.Main.POS.Receipts.ClientReceiptViewModel.PrintedOn.set(string value) Line 38 C# 
Namespace.Main.POS.Receipts.ClientReceiptViewModel.SetData(string Header) Line 79 + 0x4f bytes C# 
Namespace.Main.POS.Receipts.ClientReceiptView.ClientReceiptView(string Header) Line 28 + 0x13 bytes C# 
Namespace.Main.POS.Receipts.PrintReceipt.PrintClientReceipt(string Message) Line 12 + 0x1e bytes C# 
Namespace.Main.MainWindowView.button1_Click(object sender, System.Windows.RoutedEventArgs e) Line 23 + 0xb bytes C# 
PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) + 0x78 bytes  
PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) + 0xbe bytes 
PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args) + 0x79 bytes 
PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs e) + 0x17 bytes 
PresentationFramework.dll!System.Windows.Controls.Primitives.ButtonBase.OnClick() + 0x4b bytes 
PresentationFramework.dll!System.Windows.Controls.Button.OnClick() + 0x4d bytes 
PresentationFramework.dll!System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(System.Windows.Input.MouseButtonEventArgs e) + 0x9e bytes 
PresentationCore.dll!System.Windows.UIElement.OnMouseLeftButtonUpThunk(object sender, System.Windows.Input.MouseButtonEventArgs e) + 0x6c bytes 
PresentationCore.dll!System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(System.Delegate genericHandler, object genericTarget) + 0x31 bytes  
PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) + 0x29 bytes 
PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) + 0x3e bytes  
PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) + 0xbe bytes 
PresentationCore.dll!System.Windows.UIElement.ReRaiseEventAs(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args, System.Windows.RoutedEvent newEvent) + 0x114 bytes  
PresentationCore.dll!System.Windows.UIElement.OnMouseUpThunk(object sender, System.Windows.Input.MouseButtonEventArgs e) + 0xc5 bytes 
PresentationCore.dll!System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(System.Delegate genericHandler, object genericTarget) + 0x31 bytes  
PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) + 0x29 bytes 
PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) + 0x3e bytes  
PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) + 0xbe bytes 
PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args) + 0x79 bytes 
PresentationCore.dll!System.Windows.UIElement.RaiseTrustedEvent(System.Windows.RoutedEventArgs args) + 0x41 bytes 
PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs args, bool trusted) + 0x2c bytes  
PresentationCore.dll!System.Windows.Input.InputManager.ProcessStagingArea() + 0x1ff bytes 
PresentationCore.dll!System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs input) + 0x45 bytes 
PresentationCore.dll!System.Windows.Input.InputProviderSite.ReportInput(System.Windows.Input.InputReport inputReport) + 0x62 bytes 
PresentationCore.dll!System.Windows.Interop.HwndMouseInputProvider.ReportInput(System.IntPtr hwnd, System.Windows.Input.InputMode mode, int timestamp, System.Windows.Input.RawMouseActions actions, int x, int y, int wheel) + 0x2c2 bytes 
PresentationCore.dll!System.Windows.Interop.HwndMouseInputProvider.FilterMessage(System.IntPtr hwnd, MS.Internal.Interop.WindowMessage msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) + 0x67d bytes 
PresentationCore.dll!System.Windows.Interop.HwndSource.InputFilterMessage(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) + 0x75 bytes 
WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) + 0xbe bytes  
WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) + 0x7d bytes  
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) + 0x53 bytes 
WindowsBase.dll!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source, System.Delegate method, object args, int numArgs, System.Delegate catchHandler) + 0x42 bytes  
WindowsBase.dll!System.Windows.Threading.Dispatcher.InvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs) + 0xb4 bytes  
WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam) + 0x104 bytes  
[Native to Managed Transition] 
[Managed to Native Transition] 
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) + 0xc1 bytes 
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) + 0x49 bytes 
PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore) + 0x5b bytes 
PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) + 0x74 bytes 
PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window) + 0x2b bytes 
PresentationFramework.dll!System.Windows.Application.Run() + 0x1b bytes 
Namespace.App.Main() + 0x5e bytes C# 
[Native to Managed Transition] 
[Managed to Native Transition] 
mscorlib.dll!System.AppDomain.nExecuteAssembly(System.Reflection.RuntimeAssembly assembly, string[] args) + 0x9 bytes 
mscorlib.dll!System.Runtime.Hosting.ManifestRunner.Run(bool checkAptModel) + 0x6e bytes 
mscorlib.dll!System.Runtime.Hosting.ManifestRunner.ExecuteAsAssembly() + 0x90 bytes 
mscorlib.dll!System.Runtime.Hosting.ApplicationActivator.CreateInstance(System.ActivationContext activationContext, string[] activationCustomData) + 0x65 bytes 
mscorlib.dll!System.Runtime.Hosting.ApplicationActivator.CreateInstance(System.ActivationContext activationContext) + 0xd bytes 
mscorlib.dll!System.Activator.CreateInstance(System.ActivationContext activationContext) + 0x44 bytes 
Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssemblyDebugInZone() + 0x23 bytes 
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x63 bytes 
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool ignoreSyncCtx) + 0xb0 bytes  
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x2c bytes  
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes 
[Native to Managed Transition] 

Затем после печатиDlg.PrintVisual (управление, «Мое приложение»); выдается, квитанция распечатывается, а затем стек вызовов в точке останова для get {return _PrintedOn; }:

Namespace.Main.POS.Receipts.ClientReceiptViewModel.PrintedOn.get() Line 37 C# 
[Native to Managed Transition] 
PresentationFramework.dll!MS.Internal.Data.PropertyPathWorker.GetValue(object item, int level) + 0x108 bytes  
PresentationFramework.dll!MS.Internal.Data.PropertyPathWorker.RawValue(int k) + 0x4a bytes 
PresentationFramework.dll!MS.Internal.Data.PropertyPathWorker.RawValue() + 0x12 bytes 
PresentationFramework.dll!MS.Internal.Data.ClrBindingWorker.RawValue() + 0x11 bytes 
PresentationFramework.dll!System.Windows.Data.BindingExpression.TransferValue(object newValue, bool isASubPropertyChange) + 0xa7 bytes 
PresentationFramework.dll!System.Windows.Data.BindingExpression.Activate(object item) + 0x194 bytes 
PresentationFramework.dll!System.Windows.Data.BindingExpression.AttachToContext(System.Windows.Data.BindingExpression.AttachAttempt attempt) + 0x38d bytes 
PresentationFramework.dll!System.Windows.Data.BindingExpression.MS.Internal.Data.IDataBindEngineClient.AttachToContext(bool lastChance) + 0x19 bytes  
PresentationFramework.dll!MS.Internal.Data.DataBindEngine.Task.Run(bool lastChance) + 0x31 bytes  
PresentationFramework.dll!MS.Internal.Data.DataBindEngine.Run(object arg) + 0xb6 bytes 
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) + 0x53 bytes 
WindowsBase.dll!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source, System.Delegate method, object args, int numArgs, System.Delegate catchHandler) + 0x42 bytes  
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeImpl() + 0x8d bytes 
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(object state) + 0x38 bytes 
mscorlib.dll!System.Threading.ExecutionContext.runTryCode(object userData) + 0x51 bytes 
[Native to Managed Transition] 
[Managed to Native Transition] 
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x6a bytes  
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool ignoreSyncCtx) + 0x7e bytes  
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x2c bytes  
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.Invoke() + 0x68 bytes 
WindowsBase.dll!System.Windows.Threading.Dispatcher.ProcessQueue() + 0x15e bytes  
WindowsBase.dll!System.Windows.Threading.Dispatcher.WndProcHook(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) + 0x63 bytes 
WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) + 0xbe bytes  
WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) + 0x7d bytes  
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) + 0x53 bytes 
WindowsBase.dll!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source, System.Delegate method, object args, int numArgs, System.Delegate catchHandler) + 0x42 bytes  
WindowsBase.dll!System.Windows.Threading.Dispatcher.InvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs) + 0xb4 bytes  
WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam) + 0x104 bytes  
[Native to Managed Transition] 
[Managed to Native Transition] 
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) + 0xc1 bytes 
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) + 0x49 bytes 
PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore) + 0x5b bytes 
PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) + 0x74 bytes 
PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window) + 0x2b bytes 
PresentationFramework.dll!System.Windows.Application.Run() + 0x1b bytes 
Namespace.App.Main() + 0x5e bytes C# 
[Native to Managed Transition] 
[Managed to Native Transition] 
mscorlib.dll!System.AppDomain.nExecuteAssembly(System.Reflection.RuntimeAssembly assembly, string[] args) + 0x9 bytes 
mscorlib.dll!System.Runtime.Hosting.ManifestRunner.Run(bool checkAptModel) + 0x6e bytes 
mscorlib.dll!System.Runtime.Hosting.ManifestRunner.ExecuteAsAssembly() + 0x90 bytes 
mscorlib.dll!System.Runtime.Hosting.ApplicationActivator.CreateInstance(System.ActivationContext activationContext, string[] activationCustomData) + 0x65 bytes 
mscorlib.dll!System.Runtime.Hosting.ApplicationActivator.CreateInstance(System.ActivationContext activationContext) + 0xd bytes 
mscorlib.dll!System.Activator.CreateInstance(System.ActivationContext activationContext) + 0x44 bytes 
Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssemblyDebugInZone() + 0x23 bytes 
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x63 bytes 
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool ignoreSyncCtx) + 0xb0 bytes  
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x2c bytes  
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes 
[Native to Managed Transition] 
+1

Ваш стек вызовов, вероятно, имеет только одну запись, потому что вы включили «только мой код» в параметрах отладки. Выключение этого режима должно показать вам последовательность вызовов WPF, хотя я не знаю, насколько это будет полезно. – GazTheDestroyer

+0

Обновлено с полным стеком вызовов – nurgent

+0

Возможно, вы закончили свое приложение. Я сделал это так же, и когда я прочитал это, я понял, что читаю себя. Ваш код кажется доказательством концепции, поскольку вы помещаете жестко заданные значения в модель view.I использовали paginator для очень длинных квитанций. Я думал, что этот путь был странным. Большинство конкурентов используют для этого механизмы отчетности, и пользователь может настроить все. Но мы не можем использовать этот метод. Но проблема, казалось, была решена для меня при установке datacontext в конструкторе, как и вы. – GorillaApe

ответ

3

Используйте Dispatcher для очередного задания на печать позднее DispatcherPriority, чем DataBind. Таким образом, вся ваша привязка данных обрабатывается до выполнения задания на печать.

Dispatcher.BeginInvoke(DispatcherPriority.Loaded, 
    new Action(delegate() { printDlg.PrintVisual(control, "My App"); })); 
+0

Это сработало, спасибо. – nurgent

2

Я не знаю, что инициирует первоначальное обновление привязки (вы можете сказать из стека вызовов?). Мне было бы интересно узнать тоже.

В одном из способов может быть установлено значение в вашем ViewModel после оно было настроено как контекст представления. Возможно, уведомление PropertyChanged заставит привязку обновить, например:

public ClientReceiptView(string Header) 
{ 
    InitializeComponent(); 
    vm = new ClientReceiptViewModel(); 
    this.DataContext = vm; 
    vm.SetHeader(Header); 
} 

Только угадывание. :/

+0

Я изменил настройки данных вокруг и не кубиками. Я отправил трассировку стека на редактирование на главный. – nurgent

Смежные вопросы