【问题标题】:2 State WPF Button not changing ImageSource2 状态 WPF 按钮不改变 ImageSource
【发布时间】:2012-10-24 21:23:45
【问题描述】:

我无法让此按钮(其内容中包含图像)在点击时正确更改 ImageSource。这是我的 Xaml 和代码背后。

XAML:

<Window.Resources>
    <Style x:Key="NoChromeButton" TargetType="{x:Type Button}">
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
        <Setter Property="HorizontalContentAlignment" Value="Center"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="Padding" Value="1"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid x:Name="Chrome" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">
                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="#ADADAD"/>
                            <Setter Property="Opacity" TargetName="Chrome" Value="0.5"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

<Grid>
    <Button x:Name="DrawCircleButton" Height="56" Width="157" 
    Margin="10,10,0,0" VerticalAlignment="Top" 
    HorizontalAlignment="Left" Click="DrawCircleButtonClick"
            Style="{DynamicResource NoChromeButton}"
    >
        <Image x:Name="imgButtonState" >
            <Image.Source>
                <BitmapImage UriSource="Resources/off.gif" />
            </Image.Source>
        </Image>
    </Button>
    <ScrollViewer Margin="0,50,0,0">
        <TextBlock Name="textBlock1" TextWrapping="Wrap" FontSize="20" FontWeight="Bold" />
    </ScrollViewer>


</Grid>

代码背后:

private void DrawCircleButtonClick(object sender, RoutedEventArgs e)
    {
        var t = ButtonState;
        ButtonState = t;
    }

public bool ButtonState
    {
        get
        {
            return (bool)GetValue(ButtonStateProperty);
        }
        set
        {
            var t = new BitmapImage(new Uri("Resource/on.gif", UriKind.Relative));

            DrawCircleButton.Content = !value ? imgButtonState.Source = new BitmapImage(new Uri("on.gif", UriKind.Relative)) : imgButtonState.Source = new BitmapImage(new Uri("off.gif", UriKind.Relative));
            SetValue(ButtonStateProperty, !value);
        }
    }

    public static readonly DependencyProperty ButtonStateProperty = DependencyProperty.Register("ButtonState", typeof(bool), typeof(bool));

所以最初,该按钮设置为“关闭”。但是当它被点击时,它会在“开”和“关”之间切换。我确定我做错了什么,因为显示的是图像路径的文本。有什么想法吗?

【问题讨论】:

    标签: wpf button user-controls wpf-controls imagesource


    【解决方案1】:

    首先,WPF 还有一个ToggleButton。也许在这里更合适。

    现在你的错误。它基本上在以下行:

    DrawCircleButton.Content = !value ? imgButtonState.Source = new BitmapImage(new Uri("on.gif", UriKind.Relative)) : imgButtonState.Source = new BitmapImage(new Uri("off.gif", UriKind.Relative));
    

    您将新的 BitmapImage 分配给 Button 的 Content 属性。由于 Button 的 ContentPresenter 无法处理该类型,它只显示 ToString() 的结果。如果您只是放弃作业并编写以下内容,它将起作用。内容没有改变,只是图像的来源已经是按钮的内容。

    imgButtonState.Source = value
        ? new BitmapImage(new Uri("on.gif", UriKind.Relative))
        : new BitmapImage(new Uri("off.gif", UriKind.Relative));
    

    但是,您的依赖属性ButtonState 的定义仍然存在严重问题。如果你想这样定义它,你必须从 Button 派生并编写如下声明:

    public class MyButton : Button
    {
        public static readonly DependencyProperty ButtonStateProperty =
            DependencyProperty.Register(
                "ButtonState", typeof(bool), typeof(MyButton),
                new FrameworkPropertyMetadata(ButtonStatePropertyChanged));
    
        public bool ButtonState
        {
            get { return (bool)GetValue(ButtonStateProperty); }
            set { SetValue(ButtonStateProperty, value); }
        }
    
        private static void ButtonStatePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            ((MyButton)obj).imgButtonState.Source = (bool)e.NewValue
                ? new BitmapImage(new Uri("on.gif", UriKind.Relative))
                : new BitmapImage(new Uri("off.gif", UriKind.Relative));
        }
    }
    

    您也不应该在依赖属性的 CLR 包装器中执行 GetValue/SetValue 以外的任何操作。相反,您应该使用如上所示的 PropertyChangedCallback。请参阅Checklist for Defining a Dependency Property 中的实现包装器部分。

    如果您不想从 Button 派生,您也可以将 ButtonState 定义为 attached property

    【讨论】:

    • 感谢克莱门斯的详细回复。它有效,但我想知道,在您的第二个代码块中,包含该按钮的 XAML 是否具有单击事件?我尝试使用您提供的代码,并将“MyButton”更改为我在 XAML 中定义的按钮。
    • 是的,当然。派生的 MyButton 继承 Button 的所有属性、方法和事件。它可以在任何可以使用 Button 的地方使用。在 XAML 中,只需将 &lt;Button ...&gt; 替换为 &lt;local:MyButton ...&gt;,其中 local 是包含 MyButton 的命名空间/程序集的 XML 命名空间引用。
    【解决方案2】:

    使用Image 而不是BitmapImage 作为Button 的内容。此外,请使用Image.Source = "/Resources/YourFile.png",而不是在 XAML 和代码中声明位图图像。

    【讨论】:

      猜你喜欢
      • 2018-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多