【问题标题】:reloading image in wpf window after changing the image更改图像后在 wpf 窗口中重新加载图像
【发布时间】:2018-08-31 08:58:09
【问题描述】:

最近在用WPF和C#,想做一个A4页面的编辑器(A4大小的JPG模板)

问题是,我想在 JPG 上的某个位置放置一些文本,以便在我编写文本时能够看到它(就像实时预览一样)。

这是我现在所取得的成就:

XAML

<Window x:Class="Tut.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:Tut"
    mc:Ignorable="d"
    Title="Neshalet Logo ltd." Height="900" Width="1400">
<Border Padding="10">
    <StackPanel Margin="0,10,0,0">
        <Grid Height="839">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width=".3*"/>

            </Grid.ColumnDefinitions>

            <TextBlock Margin="0,2,22,817" HorizontalAlignment="Right" Grid.Column="2" FontSize="15">
                בחר מוצר
            </TextBlock>

            <!-- Combo box for product type -->
            <ComboBox x:Name="productType" Grid.Column="1"  VerticalAlignment="Top" Height="25" Margin="10,0,17,0"  >
                <ComboBoxItem>באנרים</ComboBoxItem>
                <ComboBoxItem>שקפים וניירות</ComboBoxItem>
                <ComboBoxItem>וינילים</ComboBoxItem>
                <ComboBoxItem>קשיחים הדפסה ישירה</ComboBoxItem>
                <ComboBoxItem>הדבקה</ComboBoxItem>
            </ComboBox>

            <Image Source ="/Resources/a4.jpg" Grid.Column="0" Margin="10,35,0,0" HorizontalAlignment="Left" VerticalAlignment="Top">
            </Image>

                <!-- Main window -->
            <StackPanel Grid.Column="1" Grid.ColumnSpan="2" Margin="10,40,0,0">
                <Grid  Height="492">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="3*"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>

                    <!-- SO Number-->
                    <TextBlock Grid.Column="1" FontSize="16" HorizontalAlignment="Right" Margin="0,5,22,472"><Run Text="מספר הזמנה"/></TextBlock>
                    <TextBox x:Name="SO" DataContextChanged="drawSO" Height="25" HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="0,0,5,0"/>

                    <!-- Costumer name -->
                    <TextBlock Grid.Column="1" FontSize="16" HorizontalAlignment="Right" Margin="0,34,22,440"><Run Text="שם לקוח"/></TextBlock>
                    <TextBox Grid.Column="0" Height="25" HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="0,30,5,0"/>

                    <!-- Order date -->
                    <TextBlock Grid.Column="1" FontSize="16" HorizontalAlignment="Right" Margin="0,64,22,410"><Run Text="תאריך"/></TextBlock>
                    <Button Grid.Column="1" Margin="9,62,122,410" Click="getDate" Content="היום" RenderTransformOrigin="0.5,0.5"/>
                    <DatePicker x:Name="todaysDate" Grid.Column="0" Height="25" HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="0,60,5,0"/>

                    <!-- Supply date -->
                    <TextBlock Grid.Column="1" FontSize="16" HorizontalAlignment="Right" Margin="0,93,22,381"><Run Text="תאריך אספקה"/></TextBlock>
                    <DatePicker x:Name ="deliveryDate" Margin="0,90,5,377"  />

                    <!-- Folder -->
                    <TextBlock Grid.Column="1" FontSize="16" HorizontalAlignment="Right" Margin="0,123,22,351"><Run Text="נשמר בתיקיה"/></TextBlock>
                    <ComboBox x:Name="folderName" Grid.Column="0" Margin="0,120,5,347">
                        <ComboBoxItem Content="ktanot"/>
                        <ComboBoxItem Content="GZM"/>
                        <ComboBoxItem Content="UV"/>
                        <ComboBoxItem Content="SLAVA WATER PRINTS"/>
                    </ComboBox>

                    <!-- Folder -->
                    <TextBlock Grid.Column="1" FontSize="16" HorizontalAlignment="Right" Margin="0,154,22,320"><Run Text="קוד משלוח"/></TextBlock>
                    <ComboBox x:Name="DeliveryCode" Grid.Column="0" Margin="0,150,5,317">
                        <ComboBoxItem Content="איסוף עצמי"/>
                        <ComboBoxItem Content="מסירה"/>
                        <ComboBoxItem Content="משלוח"/>
                    </ComboBox>

                    <Button Margin="230,362,270,96" Click="Button_Click">
                        כאן
                    </Button>

                </Grid>
            </StackPanel>
            <Label Content="תצוגה מקדימה" HorizontalAlignment="Center" VerticalAlignment="Top" Grid.Column="0"/>

        </Grid>

        <!-- Image preview -->

    </StackPanel>
</Border>

C#

    public partial class MainWindow : Window
{
    public MainWindow() => InitializeComponent();

    DateTime today = DateTime.Today.Date;

    String path = @"/Resources/a4.jpg";

    Bitmap order = null;

    Font f = new Font("Arial", 200, GraphicsUnit.Pixel);

    private void getDate(object sender, RoutedEventArgs e)
    {
        String t = today.ToShortDateString();
        todaysDate.Text = t;
    }


    private void drawSO(object sender, DependencyPropertyChangedEventArgs e)
    {

    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        String orderNum = SO.Text;
        using (var stream = File.OpenRead(path))
        {
            order = (Bitmap)Bitmap.FromStream(stream);
        }
        using (order)
        using (var graphics = Graphics.FromImage(order))
        using (f)
        {
            graphics.DrawString(orderNum, f, System.Drawing.Brushes.White, order.Height/2, order.Width/2);
            order.Save(path);
        }

    }
}

问题是我让程序只在单击按钮时写入文本(正如您在 Button_Click() 上看到的那样,但我想显示我在 SO Number 文本上写的文本在我写的时候盒子。 当我在按钮点击事件上写文本和 not 时,有什么方法可以刷新窗口上的图像视图?

这是一个例子: 我希望在文本框中输入的文本会在 jpg 上

【问题讨论】:

  • 如果您使用了绑定,那么您可以将TextBlockText 值绑定到TextBoxText 属性。问题已解决,确保设置UpdateSourceTrigger=PropertyChanged

标签: c# wpf image xaml data-binding


【解决方案1】:

只需绑定TextBlockText 属性即可使用TextBoxText
像这样:

<TextBlock Grid.Column="1" FontSize="16" HorizontalAlignment="Right" Margin="0,5,22,472" Text="{Binding ElementName=SO, Path=Text, UpdateSourceTrigger=PropertyChanged}"/>  

更新

在 cmets 和已编辑的问题之后。

您可以将TextBlock 放在Image 之后的网格中,然后生成包含所有视觉效果的新图像。
它会是这样的:

<Grid x:Name="imageToExport">
    <Image Source ="/Resources/a4.jpg" Grid.Column="0" Margin="10,35,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"/>
    <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Text="Some text here that will appear on top of the image"/><!-- The text property can use binding instead -->
</Grid>  

然后你将它保存为 jpeg,像这样:

Image myImage = new Image();
FormattedText text = new FormattedText("ABC",
    new CultureInfo("en-us"),
    FlowDirection.LeftToRight,
    new Typeface(this.FontFamily, FontStyles.Normal, FontWeights.Normal, new 
FontStretch()),
    this.FontSize,
    this.Foreground);

DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
drawingContext.DrawText(text, new Point(2, 2));
drawingContext.Close();

RenderTargetBitmap bmp = new RenderTargetBitmap(180, 180, 120, 96, 
PixelFormats.Pbgra32);
bmp.Render(drawingVisual);//In here you could just pass the name of the grid "imageToExport"
myImage.Source = bmp;  

注意
请注意保存视觉的代码来自MSDN

【讨论】:

  • 我想我被误解了..你给的解决方案改变了 textBlock ,我想在图像上粘贴一个文本,在 TextBox 中粘贴相同的文本。编辑了我的问题,请看一下:)
  • 更新了我的答案,我想这就是你要找的:-)
【解决方案2】:

问题是我让程序只在单击按钮时写入文本(如您在 Button_Click() 上看到的那样,但我想在我写的时候显示我在 SO Number 文本框中写的文本. 有没有办法在我写文本而不是Button点击事件时刷新窗口上的图像视图?

尝试为TextBox 处理TextChanged 事件,而不是为Button 处理Click 事件:

<TextBox x:Name="SO" TextChanged="" ... />

private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    String orderNum = SO.Text;
    using (var stream = File.OpenRead(path))
    {
        order = (Bitmap)Bitmap.FromStream(stream);
    }
    using (order)
    using (var graphics = Graphics.FromImage(order))
    using (f)
    {
        graphics.DrawString(orderNum, f, System.Drawing.Brushes.White, order.Height / 2, order.Width / 2);
        order.Save(path);
    }
}

请注意,每次按键都会调用事件处理程序。如果出于性能原因不希望这样做,您可以考虑绑定到string 属性并按照here 的建议实施一些延迟。

【讨论】:

  • 这是我一直在寻找的评论!你有我的心上人!但有 2 个问题:1. 输入超过 1 个字符时出现异常 2. 您发布的链接已损坏:(
  • @t0nty:链接已修复。您在哪里遇到了哪些例外情况?
  • System.ArgumentException: '参数无效。'在线 graphics.DrawString(orderNum, f, System.Drawing.Brushes.White, order.Height / 2, order.Width / 2);
  • 嗯,和以前的代码一样。您需要调试并找出有效调用和失败调用之间的区别。
  • 知道了,它把第一个字母作为整个字符串,如果我再添加一个字符,程序就会崩溃,延迟应该有效吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-17
  • 1970-01-01
  • 2011-07-03
  • 1970-01-01
  • 2014-02-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多