WPF在单击按钮时更改按钮上的xaml图标

时间:2016-04-27 15:13:57

标签: c# wpf xaml mvvm icons

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

我做了一堆阅读并在这个网站上找到了问题:WPF Change button background image when clicked

我接受了答案并提出了这个问题。

<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>

我得到的错误是视觉工作室在Setters和状态中强调了属性

“会员'来源'无法识别或无法访问”

2 个答案:

答案 0 :(得分:3)

你现在拥有的XAML存在一些问题。

正如其他人所指出的,WPF画布上没有Source属性。如果您要做的只是制作已经定义的按钮内容画布,您可以使用相同的技术将Button的Content属性绑定到App.xaml中定义的Canvases(或者可能在任何地方) )

您可能遇到的另一个问题是数据触发器中的绑定。我没有测试过,但我认为你在用户控件期望的样式中没有相同的datacontext(或包含按钮的任何东西)看起来不像数据上下文是一个问题,我想我正在考虑模板问题

另外,我不确定你的ChangePnumTextState命令在做什么,但是你有没有理由在画布中作为参数发送?如果您的命令只是在IsPnumLocked上更改bool值,那么您应该能够处理XAML中的所有内容并保持关注点分离。

这是一个简单的更改,使按钮的内容为您定义的画布:

<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>

请注意,我们只是将按钮的内容设置为您已定义的画布,而不是尝试设置画布的来源。

此外,绑定上的RelativeSource应该处理datacontext解析(尽管你需要确保你搜索的相对源具有你所追求的datacontext)

编辑: 另一种方法是根据bool值为我的​​画布路径创建一个转换器(我假设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>

答案 1 :(得分:1)

您正尝试在Source对象上设置Canvas属性。该控件没有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>