简体   繁体   English

在wpf中动态地将图像分配给文本框模板

[英]Dynamically assign image to textbox template in wpf

I had implemented a template for textbox to show image inside it, but the problem I facing is that I unable to show image dynamically. 我已经为文本框实现了一个模板来显示其中的图像,但我遇到的问题是我无法动态显示图像。 Here is my code 这是我的代码

Window.xaml Window.xaml

<TextBox Style="{StaticResource imageTextBox}" />

Here is my textbox template 这是我的文本框模板

<Style TargetType="Control" x:Key="imageTextBox">
    <Setter Property="Margin" Value="0,0,0,8"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Control">
                <Border x:Name="bg" BorderThickness="1" CornerRadius="3" BorderBrush="Gray">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="30"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <TextBox Style="{DynamicResource BasicTextBox}" Grid.Column="1" 
                                 Foreground="{TemplateBinding Foreground}" 
                                 Background="{TemplateBinding Background}" 
                                 FontFamily="{TemplateBinding FontFamily}"
                                 FontSize="{TemplateBinding FontSize}"
                                 FontWeight="{TemplateBinding FontWeight}"
                                 MinWidth="340" Margin="1" />
                        <Image Source="Images/img_1.gif" Width="20"/>
                    </Grid>
                </Border>

                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="BorderBrush" TargetName="bg" Value="Black"/>
                    </Trigger>
                    <Trigger Property="IsFocused" Value="True">
                        <Setter Property="BorderBrush" TargetName="bg" Value="Black"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style x:Key="BasicTextBox" TargetType="{x:Type TextBox}">
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="BorderThickness" Value="0"/>
</Style>

You can use a {Binding} for the <Image.Source> property. 您可以使用{Binding}作为<Image.Source>属性。 Here's an example as a LinqPad query ( get LinqPad free ): 是一个LinqPad查询示例免费获得LinqPad ):

void Main()
{
    // Need to parse XAML since LinqPad doesn't have an integrated XAML build
    var xaml = @"
    <Grid xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
    <Grid.Resources>
    <Style TargetType=""Control"" x:Key=""imageTextBox"">
        <Setter Property=""Margin"" Value=""0,0,0,8""/>
        <Setter Property=""Template"">
            <Setter.Value>
                <ControlTemplate TargetType=""Control"">
                    <Border x:Name=""bg"" BorderThickness=""1"" CornerRadius=""3"" BorderBrush=""Gray"">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width=""30""/>
                                <ColumnDefinition Width=""*""/>
                            </Grid.ColumnDefinitions>
                            <TextBox Style=""{DynamicResource BasicTextBox}"" Grid.Column=""1""
                                     Foreground=""{TemplateBinding Foreground}""
                                     Background=""{TemplateBinding Background}""
                                     FontFamily=""{TemplateBinding FontFamily}""
                                     FontSize=""{TemplateBinding FontSize}""
                                     FontWeight=""{TemplateBinding FontWeight}""
                                     MinWidth=""340"" Margin=""1"" />
                            <Image Source=""{Binding Image}"" Width=""20""/>
                        </Grid>
                    </Border>

                    <ControlTemplate.Triggers>
                        <Trigger Property=""IsMouseOver"" Value=""True"">
                            <Setter Property=""BorderBrush"" TargetName=""bg"" Value=""Black""/>
                        </Trigger>
                        <Trigger Property=""IsFocused"" Value=""True"">
                            <Setter Property=""BorderBrush"" TargetName=""bg"" Value=""Black""/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    </Grid.Resources>
    <TextBox Style=""{StaticResource imageTextBox}"" />
    </Grid>
    ";

    // Get some images... these could be in your resources
    var png = PngBitmapDecoder.Create(new Uri("https://upload.wikimedia.org/wikipedia/commons/9/97/Esperanto_star.png"), BitmapCreateOptions.None, BitmapCacheOption.Default);
    var vm = new ViewModel { Image = png.Frames[0] };
    var o = (FrameworkElement)XamlReader.Parse(xaml);
    // Set the image source - in this case, a view model
    o.DataContext = vm;
    // Let LinqPad display it
    PanelManager.DisplayWpfElement(o);

    // This code is for the example only, to change the image after 2 seconds.
    var dispatcher = o.Dispatcher;
    Task.Run(async () =>
    {
        await Task.Delay(2000);
        await dispatcher.BeginInvoke((Action)(() =>
        {
            png = PngBitmapDecoder.Create(new Uri("https://upload.wikimedia.org/wikipedia/commons/f/f6/Lol_question_mark.png"), BitmapCreateOptions.None, BitmapCacheOption.Default);
            vm.Image = png.Frames[0];
        }));
    });
}

// Define other methods and classes here
public class ViewModel : INotifyPropertyChanged
{
    private ImageSource _image;
    public event PropertyChangedEventHandler PropertyChanged;

    public ImageSource Image
    {
        get
        {
            return _image;
        }
        set
        {
            if (_image == value)
            {
                return;
            }

            _image = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Image)));
        }
    }
}

This example uses a simple view model as the Binding source, but it could be any source. 此示例使用简单视图模型作为Binding源,但它可以是任何源。 There is also code which changes the Image value after a 2 second delay to show you that it does in fact update. 还有一些代码在2秒延迟后更改Image值,以显示它确实更新了。 In your code, you'd omit this and use the way you want to update it. 在您的代码中,您将省略它并使用您想要更新它的方式。

At first it appears: 起初看来: 首次出现的形象

Then after update: 然后更新后: 更新后的外观

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM