WPF按钮带有图像+文本并在代码隐藏中更改图像

Bla*_*ath 1 wpf xaml image button

我正在尝试创建一个包含图像和文本的按钮.但是,可以通过运行时后面的代码来更改图像.我的图片是png,每个人都在我的ResourceDictionary中:

<BitmapImage x:Key="iconLogIn" UriSource="/Images/Icons/lock.png" />
Run Code Online (Sandbox Code Playgroud)

所以,我已经开始使用这种风格,没有Template或ContentTemplate.

<Style x:Key="MyTestButton" TargetType="{x:Type Button}">
    <Setter Property="Height" Value="80" />
    <Setter Property="Width" Value="100" />
</Style>
Run Code Online (Sandbox Code Playgroud)

我的XAML是:

<Button x:Name="cmdOption1" Style="{StaticResource MyTestButton}" Margin="8" Click="cmdOption1_Click">
    <Image Source="{DynamicResource iconLogIn}" />
</Button>
Run Code Online (Sandbox Code Playgroud)

然后,我改变图像的代码是:

cmdOption1.Content = new Image() { Source = ((BitmapImage)FindResource("iconLogOut")) };
Run Code Online (Sandbox Code Playgroud)

到目前为止,这是有效的.

但是,只保留图像,我想在图像下面放置一个文本.

所以我读过这篇文章,而HighCore的答案,选项#2,可能符合我的要求.但是,现在出现了一个新问题:

首先,这是一种新的风格,带有一个简单的模板

<Style x:Key="MyTestButton" TargetType="{x:Type Button}">
    <Setter Property="Background" Value="#EEEEEE" />
    <Setter Property="Foreground" Value="DarkSlateGray" />
    <Setter Property="Height" Value="80" />
    <Setter Property="Width" Value="100" />
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="Padding" Value="2"/>
    <Setter Property="FontSize" Value="12" />
    <Setter Property="FontWeight" Value="SemiBold" />
    <Setter Property="BorderThickness" Value="1" />
    <Setter Property="BorderBrush" Value="DarkGray" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border>
                    <StackPanel>
                        <Image Source="{Binding Tag, RelativeSource={RelativeSource TemplatedParent}}" Height="50" Width="50"/>
                        <ContentPresenter Grid.Row="0" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True" />
                    </StackPanel>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsPressed" Value="True">
                        <Setter Property="Foreground" Value="DarkOrange" />
                        <Setter Property="OpacityMask" Value="#AA888888"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Foreground" Value="Gray" />
                        <Setter Property="BorderBrush" Value="DarkGray" />
                        <Setter Property="Background" Value="White" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
</Style>
Run Code Online (Sandbox Code Playgroud)

我的新XAML是:

<Button x:Name="cmdOption1" Tag="{StaticResource iconLogIn}" Content="LOG IN" Style="{StaticResource MyTestButton}" Margin="8" Click="cmdOption1_Click" />
Run Code Online (Sandbox Code Playgroud)

*还有Tag ="{DynamicResource iconLogIn}"

我的代码背后改变了图像和文字:

cmdOption1.Tag = new Image() { Source = ((BitmapImage)FindResource("iconLogOut")) };
cmdOption1.Content = "LOG OUT";
Run Code Online (Sandbox Code Playgroud)

这样,内容文本从"登录"变为"登出".但是图像不再显示,图像中没有任何内容,也没有抛出任何错误或异常.

我想知道解决方案是什么,发生了什么?为什么图像不会改变,但却消失了?

提前致谢.

Hut*_*wer 5

我认为你应该考虑采用更清晰的方法,使用MVVM,数据绑定和INotifyPropertyChanged的实现.

首先:使用ViewModel定义用于定义ImageUri和Text的属性:

    private Uri _myImageUriProperty;
    public Uri MyImageUriProperty
    {
        get { return _myImageUriProperty; }
        set { _myImageUriProperty = value; RaisePropertyChanged(() => MyImageUriProperty); }
    }

    private string _myTextBlockProperty;
    public string MyTextBlockProperty
    {
        get { return _myTextBlockProperty; }
        set { _myTextBlockProperty = value; RaisePropertyChanged(() => MyTextBlockProperty); }
    }
Run Code Online (Sandbox Code Playgroud)

此外:在按钮内,您可以使用占位符在按钮中放置多个UI元素.并从viewmodel将它们绑定到您的属性:

    <Button x:Name="MyButton"
            Click="MyButton_OnClick">
        <StackPanel>
            <Image x:Name="MyImage"
                   Source="{Binding MyImageUriProperty}" />
            <TextBlock x:Name="MyTextBlock"
                       Text="{Binding MyTextBlockProperty}" />
        </StackPanel>
    </Button>
Run Code Online (Sandbox Code Playgroud)

最后:使用codebehind中的click事件重置viewmodel中的值(您在代码隐藏的构造函数中设置的值为DataContext.PropertyChanged事件将触发UI中的更新.

    private void MyButton_OnClick(object sender, RoutedEventArgs e)
    {
        ViewModel.MyImageUriProperty = new Uri("mynewuri.png", UriKind.Relative)
        ViewModel.MyTextBlockProperty = "LogOut";
    }
Run Code Online (Sandbox Code Playgroud)