viewmodelbase stacklayout pattern instancelocator ejemplo data content calculated data-binding xps fixedpage fixeddocument fixeddocumentsequence

data-binding - pattern - xamarin stacklayout content binding



¿Por qué pierdo mi enlace de datos cuando imprimo en un XpsDocument? (3)

La causa de este error es que el diseño de FixedPage no se actualiza antes de la escritura. Esto hace que la primera página FixedPage en el primer FixedDocument en FixedDocumentSequence se escriba incorrectamente. Esto NO AFECTA NINGUNA OTRA PÁGINA EN EL DOCUMENTO RESULTANTE , lo que hizo que esta falla / borde fuera más difícil de clavar.

Los siguientes TRABAJOS (versión reescrita del ejemplo que no funciona):

FixedPage fp = CreateFixedPageWithBinding(); fp.DataContext = CreateDataContext(); var fd = new FixedDocument(); /* PAY ATTENTION HERE */ // set the page size on our fixed document fd.DocumentPaginator.PageSize = new System.Windows.Size() { Width = DotsPerInch * PageWidth, Height = DotsPerInch * PageHeight }; // Update the layout of our FixedPage var size = fd.DocumentPaginator.PageSize; page.Measure(size); page.Arrange(new Rect(new Point(), size)); page.UpdateLayout(); /* STOP PAYING ATTENTION HERE */ var pc = new PageContent(); ((IAddChild)pc).AddChild(fp); fd.Pages.Add(pageContent); // Create a fixed document sequence and add the fixed document to it FixedDocumentSequence fds = CreateFixedDocumentSequence(); var dr = new DocumentReference(); dr.BeginInit(); dr.SetDocument(fd); dr.EndInit(); (fds as IAddChild).AddChild(dr); // Create an xps document and write the fixed document sequence to it var p = Package.Open("c://output.xps", FileMode.CreateNew); var doc = new XpsDocument(p); var writer = XpsDocument.CreateXpsDocumentWriter(doc); wri2.Write(fds); p.Flush(); p.Close();

¡Actualizar!

Encuadernación funciona El problema es que XpsDocumentWriter no escribe correctamente la primera página del primer documento de una FixedDocumentSequence. Este parece ser un problema que enfrentan muchas personas que hacen este tipo de cosas (es decir, cinco desarrolladores en todo el mundo). La solución es un poco extraña. Lo incluyo como una respuesta.

De acuerdo, es un poco más sutil de lo que sugiere la pregunta.

Tengo una serie de páginas fijas, cada una tiene su DataContext configurado individualmente. Cada FixedPage también tiene uno o más controles que están vinculados al contexto.

Si agrego estas páginas fijas a un solo FixedDocument y escribo este FixedDocument en un XpsDocument, mis bindings son desreferenciados (por así decirlo) y los valores correctos se presentan en XpsDocument.

Si añado estos FixedPages a FixedDocuments individuales (cada FP se agrega a un nuevo FD), estos FixedDocuments se agregan a FixedDocumentSequence, y esta secuencia se escribe en XpsDocument, mis enlaces NO son referenciados y mis FixedPages aparecen en blanco .

La depuración me dice que no estoy perdiendo mis enlaces o mi contexto vinculante, por lo que esa no es la causa de este error.

Aquí hay un código de muestra para ilustrar lo que está sucediendo:

// This works FixedPage fp = CreateFixedPageWithBinding(); fp.DataContext = CreateDataContext(); // Add my databound fixed page to a new fixed document var fd = new FixedDocument(); var pc = new PageContent(); ((IAddChild)pc).AddChild(fp); fd.Pages.Add(pageContent); // Create an xps document and write my fixed document to it var p = Package.Open("c://output.xps", FileMode.CreateNew); var doc = new XpsDocument(p); var writer = XpsDocument.CreateXpsDocumentWriter(doc); wri2.Write(fd); p.Flush(); p.Close(); // This does NOT work FixedPage fp = CreateFixedPageWithBinding(); fp.DataContext = CreateDataContext(); // Add my databound fixed page to a new fixed document var fd = new FixedDocument(); var pc = new PageContent(); ((IAddChild)pc).AddChild(fp); fd.Pages.Add(pageContent); // Create a fixed document sequence and add the fixed document to it FixedDocumentSequence fds = CreateFixedDocumentSequence(); var dr = new DocumentReference(); dr.BeginInit(); dr.SetDocument(fd); dr.EndInit(); (fds as IAddChild).AddChild(dr); // Create an xps document and write the fixed document sequence to it var p = Package.Open("c://output.xps", FileMode.CreateNew); var doc = new XpsDocument(p); var writer = XpsDocument.CreateXpsDocumentWriter(doc); wri2.Write(fds); p.Flush(); p.Close();

Puede ver que la única diferencia entre los dos es que estoy agregando el documento fijo a una secuencia de documentos fija, que luego se escribe.

Obviamente, cualquier magia que ocurra que provoque que se evalúe el enlace de datos y que se inserten los valores encuadernados, no sucederá cuando mis documentos fijos no se escriban en el Documento Xps. Necesito poder escribir más de un documento fijo, y el método de Escritura solo se puede llamar una vez, por lo que necesito agregar los FixedDocuments a una FixedDocumentSequence que luego escribo. ¡Pero también necesito que mi maldito enlace de datos también funcione!

Cualquier ayuda en esta situación sería apreciada. Sé que no es exactamente la parte más común del marco; Solo espero que alguien aquí tenga algo de experiencia operativa con esto (te estoy mirando, empleado de MS al acecho).


Una razón por la que pierde un enlace es porque lanza una excepción en alguna parte; desafortunadamente, esta excepción se traga en silencio y su enlace simplemente "deja de funcionar". Activa Excepciones de primera oportunidad y mira si algo es golpeado.


Encontré este problema al intentar usar XpsDocumentWriter para escribir en PrintQueue . El siguiente código imprime la primera página correctamente.

//Prints correctly FixedDocumentSequence Documents = new FixedDocumentSequence(); //some code to add DocumentReferences to FixedDocumentSequence PrintDialog printDialog = new PrintDialog { PrintQueue = LocalPrintServer.GetDefaultPrintQueue() }; printDialog.PrintTicket = printDialog.PrintQueue.DefaultPrintTicket; if (printDialog.ShowDialog() == true) { Documents.PrintTicket = printDialog.PrintTicket; XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(printDialog.PrintQueue); writer.Write(Documents, printDialog.PrintTicket); printerName = printDialog.PrintQueue.FullName; }

Si elimina printDialog.ShowDialog() y solo intenta imprimir silenciosamente en la impresora predeterminada, la primera página se imprime incorrectamente. Sin embargo, en mi caso, no necesitaba usar FixedDocumentSequence así que lo FixedDocumentSequence por un solo FixedDocument y funcionó la impresión silenciosa. Traté de actualizar el diseño en FixedPage sin éxito. Es extraño cómo la primera página se imprime bien si se muestra el cuadro de diálogo Imprimir.