WPF MVVM后台打印数据绑定问题

我正在使用wpf / mvvm开发销售点应用程序。 在交易生命周期的许多部分中,将在后台打印收据。 我已经使用其他示例在后台生成和打印收据。 我在后台打印UserControl,一切看起来都很棒。

然后我为控件创建了ViewModel,因此它可以加载要打印的事务。 我从2个基本文本框开始 – 文本标题“客户收据”和顶部标题“打印在:MM / dd / yy hh:mm tt”。

这是调试器在按下打印按钮时显示生命周期的方式:

  • 创建新的控件实例。
  • 创建ViewModel的新实例
  • 设置INPC属性的文本
  • 在Control上运行一个小节以获得所需的预打印尺寸
  • 加载打印对话框并检索名称打印队列
  • 缩放控件的大小以适合收据纸(不应该为我当前选择的打印机缩放,因为ImageArea宽度设置与我的UC相同)
  • 根据“新”缩放图像大小重新测量和排列网格
  • 调用PrintDialog.PrintVisual – 发送UserControl
  • 打印机吐出收据 – 没有数据绑定文本
  • 然后,我的调试器进入get {return _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"); 

和View构造函数(带参数)

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

编辑:通过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] 

然后在printDlg.PrintVisual(控件,“我的应用程序”)之后; 发出后,收据打印出来然后断点上的调用堆栈获取{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] 

使用Dispatcher将打印作业DataBind稍后的DispatcherPriority而不是DataBind 。 这样,所有数据绑定都会在打印作业之前得到处理。

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

我不知道是什么触发了初始绑定更新(你能从你的调用堆栈中得知吗?)。 我也有兴趣了解一下。

解决它的一种方法可能是在将ViewModel设置为视图上下文设置它们。 也许PropertyChanged通知会强制绑定更新,例如:

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

只是猜测。 :/