En WPF, copiar (o "clonar") elementos casi nunca es correcto. Esto efectivamente hace que esto sea una pregunta XY Problem. Es decir. usted solo piensa que necesita literalmente clonar los elementos en su árbol visual. Pero tú no.
El enfoque idiomático y correcto aquí es declarar DataTemplate
que representa los datos que desea imprimir. Por supuesto, eso también significa que los datos que desea imprimir están a su vez representados por una clase de modelo de vista, para la cual se ha declarado DataTemplate
(es decir, a través de la propiedad DataType
).
Por ejemplo:
<DataTemplate DataType={x:Type PrintableViewModel}>
<!-- template contents go here -->
</DataTemplate>
El ser PrintableViewModel
clase, por supuesto, una clase de vista del modelo que contiene los datos que desea utilizar para rellenar el árbol visual que será impreso.
En el XAML para su interfaz de usuario, usted entonces lo usan algo como esto:
<ContentControl Content={Binding PrintableViewModelProperty}/>
es decir, Vincular la propiedad Content
a una propiedad en el objeto actual DataContext
que devuelve una instancia de su PrintableViewModel
, y dejar que el ContentControl
muestre los datos de manera apropiada.
WPF buscará la plantilla de datos adecuada y la aplicará para visualizarla en el ContentControl
. Cuando desee imprimir los datos, a continuación, sólo hacer algo como esto:
PrintDialog printDialog = new PrintDialog();
if (printDialog.ShowDialog() == true)
{
ContentControl contentControl = new ContentControl { Content = ((ViewModelClass)DataContext)PrintableViewModelProperty};
// This part with the margins is not strictly relevant to your question per se,
// but it's useful enough to be worth including here for future reference
PageImageableArea area = printDialog.PrintQueue.GetPrintCapabilities(printDialog.PrintTicket).PageImageableArea;
contentControl.Margin = new Thickness(area.OriginWidth, area.OriginHeight,
printDialog.PrintableAreaWidth - area.ExtentWidth - area.OriginWidth,
printDialog.PrintableAreaHeight - area.ExtentHeight - area.OriginHeight);
// This shows retrieving the data template which is declared using the DataType
// property. Of course, if you simply declare a key and reference it explicitly
// in XAML, you can just use the key itself here.
DataTemplateKey key = new DataTemplateKey(typeof(MazeViewModel));
contentControl.ContentTemplate = (DataTemplate)FindResource(key);
printDialog.PrintVisual(contentControl, "MazeGenerator");
}
Esto hará que WPF para reutilizar de forma automática la plantilla que ya se ha descrito para la clase PrintableViewModel
, poblando el ContentControl
's visual subárbol de acuerdo con esa plantilla, duplicando el visual que se muestra en la pantalla, pero sin tener que hacer ningún tipo de clonación explícita de elementos de la interfaz de usuario.
Lo anterior ilustra cómo reutilizar exactamente la representación visual. Pero, por supuesto, si desea personalizar la salida con el fin de imprimir, es tan simple como declarar que se usa un DataTemplate
diferente cuando imprime.
Existen limitaciones en este enfoque. Vea http://msdn.microsoft.com/en-us/library/ms754193.aspx. – JeffFerguson
Si desea restaurar el elemento al mismo tamaño, vuelva a llamar 'clone.Arrange (New Rect (0, 0, orginal.ActualWidth, orginal.ActualHeight))' y 'clone.UpdateLayout()', pero primero debe realizar el reparto a un 'UIElement'. – Peter