代码之家  ›  专栏  ›  技术社区  ›  Edward Tanguay

有没有一种简单的/内置的方法来获得XAML元素的精确副本(克隆)?

  •  13
  • Edward Tanguay  · 技术社区  · 15 年前

    我需要制作XAML区域 可打印 所以我们要做这个按钮处理程序:

    private void Button_Click_Print(object sender, RoutedEventArgs e)
    {
        Customer.PrintReport(PrintableArea);
    }
    

    不同的 比屏幕上显示的要好得多,比如:

    public void PrintReport(FrameworkElement fwe)
    {
        StackPanel sp = new StackPanel();
        sp.Children.Add(fwe);
        TextBlock tb = new TextBlock();
        tb.Text = "hello";
        sp.Children.Add(tb);
    
        PrintDialog dialog = new PrintDialog();
        if (dialog.ShowDialog() == true)
        { 
            dialog.PrintVisual(sp, "Print job"); 
        }
    }
    

    但是上面给了我以下的信息 :

    另一个元素的逻辑子元素。 先断开它。

    我可以想象:

    FrameworkElement fwe2 = FrameworkElement.Clone(fwe); //pseudo-code
    
    3 回复  |  直到 15 年前
        1
  •  9
  •   reSPAWNed    14 年前

    我在当前的项目中遇到了一个类似的问题,并用这个代码解决了它。

    public static class ExtensionMethods
    {
        public static T XamlClone<T>(this T original)
            where T : class
        {
            if (original == null)
                return null;
    
            object clone;
            using (var stream = new MemoryStream())
            {
                XamlWriter.Save(original, stream);
                stream.Seek(0, SeekOrigin.Begin);
                clone = XamlReader.Load(stream);
            }
    
            if (clone is T)
                return (T)clone;
            else
                return null;
        }
    }
    

        2
  •  4
  •   Peter Duniho    9 年前

    在WPF中,复制(或“克隆”)元素几乎是不正确的。这实际上是一个 XY Problem 认为 你需要在你的视觉树中克隆元素。但你没有。

    这里惯用且正确的方法是声明 DataTemplate 表示要打印的数据的。当然,这也意味着要打印的数据依次由视图模型类表示,对于该类 数据模板 DataType 属性)。

    <DataTemplate DataType={x:Type PrintableViewModel}>
      <!-- template contents go here -->
    </DataTemplate>
    

    这个 PrintableViewModel 当然,类是一个视图模型类,其中包含要用于填充将要打印的可视化树的数据。

    在UI的XAML中,您可以这样使用它:

    <ContentControl Content={Binding PrintableViewModelProperty}/>
    

    一、 e.捆扎 Content 属性中的属性 DataContext 可打印视图模型 ,让 ContentControl 适当地显示数据。

    内容控制 . 当你想的时候 打印

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

    这将导致WPF自动重用您已经描述的模板 可打印视图模型 类,填充 的可视化子树,复制您在屏幕上显示的可视化内容,但不必对UI元素进行任何形式的显式克隆。


    以上说明了如何准确地重用可视化表示。当然,如果您希望定制输出以进行打印,那么只需声明一个不同的 打印时使用。

        3
  •  -1
  •   Anvaka    15 年前

    我相信应该有一个简单的方法来做的副本(除了从父分离,打印和附加回来)。比如你可以试试 XamlWriter 写xaml,然后通过 XamlReader . 但我怀疑这样可能会有一些绑定和布局错误。

    相反,我会尝试使用 WriteableBitmap 拍摄可打印区域的快照并打印。这样你就可以创建光栅和松散向量,但我在打印方面还不够好,不能说它是好是坏。不管怎样,你可以试试看:)。

    干杯,安瓦卡。

    推荐文章