c# - XAML WPF 如何在 FlowDocument 上添加内嵌背景图像?

标签 c# wpf xaml

下面的代码是给Flow Document添加背景图片

<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <FlowDocument.Background>
    <ImageBrush ImageSource="C:\licorice.jpg" />
  </FlowDocument.Background>
  <Paragraph>
    <Run>Hello World!</Run>
  </Paragraph>
</FlowDocument>

问题是,如何更改 ImageSource 以便将图像数据作为字符串存储在 xaml 文件中? ImageBrush 是密封的,所以我无法从中获取。我正在寻找这样的东西:

<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <FlowDocument.Background>
    <InlineImageBrush base64Source="iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCA..." /> <!--does not work-->
  </FlowDocument.Background>
  <Paragraph>
    <Run>Hello World!</Run>
  </Paragraph>
</FlowDocument>

最佳答案

您可以通过以下机制(桌面 WPF)执行此操作:

  1. 创建自定义DependencyObject具有一个 DependencyProperty 的子类- 64 进制图像字符串。给你的类(class)打电话,例如 ImageData 。完成此操作后,您可以将类的命名实例添加到您的 FlowDocument.Resources 中。或Window.Resources (或Grid.Resources或其他),直接在XAML中初始化base64字符串。

  2. 创建一个自定义 IValueConverter,将 Base64 字符串转换为 BitmapImage 。将此添加到您的 Window.Resources作为命名静态资源。

  3. 对于要用作流程文档背景的每个图像,添加 ImageData流文档本身的静态资源,或者更高级别的控件,例如窗口。 (注意 - 在我的旧版本 Visual Studio 上,如果将图像资源添加到流程文档本身,表单设计器会感到困惑。尽管如此,应用程序仍成功编译并运行。)

  4. 最后,添加 DataBinding对于Background.ImageBrush.ImageSource ,将其链接到您命名的 ImageData 的 Base 64 字符串属性资源并使用自定义转换器将其转换为图像。

详情如下。一、定制ImageData类非常简单:

public class ImageData : DependencyObject
{
    public static readonly DependencyProperty Base64ImageDataProperty =
        DependencyProperty.Register("Base64ImageData",
        typeof(string),
        typeof(ImageData));

    public string Base64ImageData
    {
        get { return (string)(GetValue(Base64ImageDataProperty)); }
        set { SetValue(Base64ImageDataProperty, value); }
    }
}

接下来是自定义转换器和一些与之配套的辅助实用程序:

public class Base64ImageConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string base64String = value as string;
        if (base64String == null)
            return null;
        return ImageHelper.Base64StringToBitmapImage(base64String);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

public static class ImageHelper
{
    public static BitmapImage Base64StringToBitmapImage(string base64String)
    {
        BitmapImage bitmapImage = new BitmapImage();
        bitmapImage.BeginInit();
        bitmapImage.StreamSource = new MemoryStream(Convert.FromBase64String(base64String));
        bitmapImage.EndInit();
        return bitmapImage;
    }

    public static string FileToBase64String(string filename)
    {
        using (var stream = File.Open(filename, FileMode.Open))
        using (var reader = new BinaryReader(stream))
        {
            byte[] allData = reader.ReadBytes((int)reader.BaseStream.Length);
            return Convert.ToBase64String(allData);
        }
    }
}

将其放置在窗口、应用程序的静态资源中,或者其他对您来说方便并且可以在整个应用程序中重复使用的中心位置中:

<Window x:Class="RichTextBoxInputPanel.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:w="clr-namespace:RichTextBoxInputPanel" 
    Title="RichTextBoxInputPanel" Height="600" Width="1200" Loaded="Window_Loaded">
    <Window.Resources>
        <w:Base64ImageConverter x:Key="Base64ImageConverter"></w:Base64ImageConverter>
    </Window.Resources>

您还可以将其与 ImageData 一起添加到流程文档本身的静态资源中。如下所示。

现在,添加 ImageData到流程文档的资源:

            <FlowDocument >
                <FlowDocument.Resources>
                    <w:ImageData x:Key="DocumentBackground" Base64ImageData="iVBORw0K...etc etc">
                    </w:ImageData>
                </FlowDocument.Resources>

最后,添加背景的绑定(bind)属性:

               <FlowDocument.Background>
                    <ImageBrush>
                        <ImageBrush.ImageSource>
                            <Binding Converter="{StaticResource Base64ImageConverter}" 
                                     Source="{StaticResource DocumentBackground}"
                                     Path="Base64ImageData" Mode="OneWay"></Binding>
                        </ImageBrush.ImageSource>
                    </ImageBrush>
                </FlowDocument.Background>

最后,正如我上面提到的,放置静态 ImageData流文档本身上的资源会导致 WPF 表单设计器(在 VS2008 上)抛出虚假错误。尽管出现错误,应用程序仍能成功编译并运行。移动ImageData将流文档中的静态资源转移到包含它的高级控件(例如 RichTextBox 或 FlowDocumentReader)可以解决此问题。

关于c# - XAML WPF 如何在 FlowDocument 上添加内嵌背景图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25557891/

相关文章:

c# - WPF从DataTrigger更改图像

c# - 从 Win32 图标指针创建 Direct2D BitmapSource

c# - 从 MVVM WPF 项目中的 DataGrid 选择多个项目

c# - 如何保存每周、每两周和每月的订单

c# - 奇怪的 .Net 日期时间问题

c# - 解析 M3U 文件

c# - 在 WPF/MVVM 中动态添加用户控件

c# - 比较运算符后的浮点表达式和比率表达式的正则表达式

wpf - 在运行时在 MVVM 中将 WPF ListBox ItemsSource 从 ObservableCollection<T> 切换到 CollectionViewSource

xaml - 有没有办法在另一个 XAML 文件中包含 XAML 文件?