WPF单击按钮时更改XAML图标

4

我正在尝试创建一个按钮,用于锁定和解锁文本框。当文本框被禁用时,按钮显示一个锁定的图标;当文本框被启用时,按钮显示一个未锁定的锁。

我已经阅读了很多资料,并在此网站上找到了相关问题:WPF更改按钮背景图像

我采用了这个答案,得出了以下内容。

<Button Grid.Row="0" Command="{Binding ChangePnumTextState}" CommandParameter="{Binding ElementName=ButtonCanvas, Path=Source}">
    <Canvas Name="ButtonCanvas">
         <Canvas.Style>
              <Style TargetType="{x:Type Canvas}">
                   <Style.Triggers>
                        <DataTrigger Binding="{ Binding IsPNumLocked}" Value="True">
                            <Setter Property="Source" Value="{StaticResource appbar_lock}" />
                        </DataTrigger>
                        <DataTrigger Binding="{ Binding IsPNumLocked}" Value="False">
                            <Setter Property="Source" Value="{StaticResource appbar_unlock}" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
          </Canvas.Style>
     </Canvas>
</Button>

我已经把这批图标http://modernuiicons.com/导入到XAML文件中,需要时就会绘制出来。
我已经找了许多示例,但没有找到如何使用SVG而不是图片的示例。
编辑
好吧,有人指出SVG在WPF中不起作用,我可能只是混淆了名称。这里有一个我在资源库中使用的代码示例,用于获取图标。
<Canvas x:Key="appbar_3d_obj" Width="76" Height="76" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
    <Path Width="40" Height="40" Canvas.Left="18" Canvas.Top="18" Stretch="Fill" Fill="{DynamicResource BlackBrush}" Data="F1 M 18,21.7037L 43.9259,18L 58,25.4074L 58,54.2963L 32.8148,58L 18,49.1111L 18,21.7037 Z "/>
</Canvas>

我遇到的错误是Visual Studio在Setters和States中下划线标记了Property,并且显示“成员'Source'未被识别或无法访问”。

Wpf不支持SVG。但是有Xaml图标。 - Pikoh
好的,那可能就是我想表达的意思了。我会更新我的问题以反映这一点。谢谢。 - Fresh
无论如何,你的代码看起来没问题,你遇到了什么问题? - Pikoh
@Pikoh 哎呀,我也把这个加到我的问题里了,但是我得到的错误是在设置器中,我得到了一个错误:“成员'Source'未被识别或不可访问”。 - Fresh
2个回答

3
您现在的XAML存在一些问题。
正如其他人指出的那样,WPF画布上没有Source属性。如果您只是想让按钮内容与已定义的画布相同,您可以使用相同的技术将按钮的Content属性绑定到App.xaml(或任何位置)中定义的画布。
另一个问题可能是您在数据触发器内部的绑定。我没有测试过,但我认为您不会从样式中得到与用户控件(或包含按钮的任何其他控件)期望的相同数据上下文。看起来数据上下文并不是问题,我想我当时是在考虑模板问题。
此外,我不确定您的ChangePnumTextState命令在做什么,但您是否有理由将画布作为参数发送?如果您的命令只是在IsPnumLocked上更改一个bool值,您应该能够在XAML中处理所有内容并保持关注点分离。
这是一个简单的更改,将按钮的内容设置为您已定义的Canvas:
<Button Command="{Binding ChangePnumTextState}">
        <Button.Style>
            <Style TargetType="{x:Type Button}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsPNumLocked}" Value="True">
                        <Setter Property="Content" Value="{StaticResource appbar_lock}"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding IsPNumLocked}" Value="False">
                        <Setter Property="Content" Value="{StaticResource appbar_unlock}"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Button.Style>
    </Button>

请注意,我们并没有试图设置画布的源,而是将按钮的内容设置为您已经定义的画布。
还有一个方法是基于布尔值(我假设IsPNumLocked是)为您的画布路径创建转换器。然后,您可以将画布作为按钮内容的子级,这样更容易包含其他内容。
示例转换器:
    public class IsPnumLockedToCanvasPathConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        bool val = (bool)value;
        return val 
            ? "F1 M 22.17,36.4216L 25.3369,36.4216L 25.3369,31.6711C 25.3369,24.6745 31.0087,19.0027 38.0053,19.0027C 45.0019,19.0027 50.6737,24.6745 50.6737,31.6711L 50.6737,36.4216L 53.841,36.4216L 53.8411,57.008L 22.17,57.008L 22.17,36.4216 Z M 45.9231,31.6711C 45.9231,27.2982 42.3782,23.7533 38.0053,23.7533C 33.6324,23.7533 30.0875,27.2982 30.0875,31.6711L 30.0875,36.4216L 45.923,36.4216L 45.9231,31.6711 Z "
            : "F1 M 22.1698,36.4215L 25.3366,36.4215L 25.3367,31.6711C 25.3367,24.6745 31.0085,19.0027 38.0051,19.0027C 45.0017,19.0027 50.6735,24.6745 50.6735,31.6711L 45.9228,31.6711C 45.9228,27.2982 42.3779,23.7533 38.0051,23.7533C 33.6322,23.7533 30.0873,27.2982 30.0873,31.6711L 30.0873,36.4216L 53.8408,36.4215L 53.8409,57.008L 22.1698,57.008L 22.1698,36.4215 Z ";
    }

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

你的按钮可以这样设置:

<Button Command="{Binding ChangePnumTextState}">
        <Button.Resources>
            <converters:IsPnumLockedToCanvasPathConverter x:Key="IsPnumLockedToCanvasPathConverter"/>
        </Button.Resources>
        <StackPanel Orientation="Vertical">
            <Canvas Width="76" Height="76" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
                <Path Width="40" Height="40" Canvas.Left="18" Canvas.Top="18" Stretch="Fill" Fill="{DynamicResource BlackBrush}" Data="{Binding IsPNumLocked, Converter={StaticResource IsPnumLockedToCanvasPathConverter}}"></Path>
            </Canvas>
            <TextBlock Text="Other Content"/>
        </StackPanel>

    </Button>

您做得非常出色。干得好! - Fresh

1
你正在尝试设置Canvas对象的Source属性,但该控件没有Source属性。 Source属性通常与Image控件一起使用。
然而,由于你正在使用Canvas,你可以将两个Path对象添加到Canvas中,直接叠放在一起。为每个Path命名,然后使用DataTriggers来更改每个Path对象的可见性。
例如:
<Button Grid.Row="0" Command="{Binding ChangePnumTextState}" CommandParameter="{Binding ElementName=ButtonCanvas, Path=Source}">
<Canvas Name="ButtonCanvas">
     <Path Name="appbar_lock" Data="...your data here..."/>
     <Path Name="appbar_unlock" Data="...your data here..."/>
     <Canvas.Style>
          <Style TargetType="{x:Type Canvas}">
               <Style.Triggers>
                    <DataTrigger Binding="{Binding IsPNumLocked}" Value="True">
                        <Setter TargetName="appbar_lock" Property="Visibility" Value="Visible" />
                        <Setter TargetName="appbar_unlock" Property="Visibility" Value="Hidden" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding IsPNumLocked}" Value="False">
                        <Setter TargetName="appbar_lock" Property="Visibility" Value="Hidden" />
                        <Setter TargetName="appbar_unlock" Property="Visibility" Value="Visible" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
      </Canvas.Style>
 </Canvas>
</Button>

好的,我有一种感觉,它与源代码有关,很可能不是画布的属性,但我不确定要用什么来替换它...我不确定你说的两个路径是什么意思...你能否写一个简短的例子给我看看? - Fresh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接