尝试了几个小时都没有成功,我很想知道为什么三个按钮中只有一个显示了图标ViewBox的内容。
我想我对控件模板的内部工作不够了解。
第一个文件ButtonProperties类是包含Icon ViewBox的附加属性的所有者。第二个文件是我的主窗口。xaml窗口应该显示3个按钮与Viewbox图标。但是只有最后一个按钮实例显示Viewbox图标。
谢谢你的帮助。
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
namespace WpfApp1
{
public class ButtonProperties : DependencyObject
{
public static readonly DependencyProperty IconViewboxProperty = DependencyProperty.RegisterAttached("IconViewbox",
typeof(Viewbox), typeof(ButtonProperties), new PropertyMetadata(null));
public static void SetIconViewbox(DependencyObject obj, Viewbox viewbox)
{
obj.SetValue(IconViewboxProperty, viewbox);
}
public static Viewbox GetIconViewbox(DependencyObject obj)
{
return (Viewbox) obj.GetValue(IconViewboxProperty);
}
}
}
MainWindow.xaml
<Window
x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="800"
Height="450"
mc:Ignorable="d">
<Window.Resources>
<ResourceDictionary>
<Viewbox x:Key="IconTrash">
<Canvas Width="24" Height="24">
<Path Data="M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z" Fill="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType=Button}}" />
</Canvas>
</Viewbox>
<Style x:Key="ButtonIcon" TargetType="Button">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}">
<ContentControl x:Name="IconControl" Content="{Binding Path=(local:ButtonProperties.IconViewbox), RelativeSource={RelativeSource TemplatedParent}}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="IconControl" Property="Opacity" Value="0.5" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style
x:Key="ButtonIconTrash"
BasedOn="{StaticResource ButtonIcon}"
TargetType="Button">
<Setter Property="local:ButtonProperties.IconViewbox" Value="{DynamicResource IconTrash}" />
</Style>
</ResourceDictionary>
</Window.Resources>
<StackPanel Orientation="Vertical">
<Button
Width="25"
Height="25"
Style="{DynamicResource ButtonIconTrash}" />
<Button
Width="25"
Height="25"
Style="{DynamicResource ButtonIconTrash}" />
<Button
Width="25"
Height="25"
Style="{DynamicResource ButtonIconTrash}" />
</StackPanel>
</Window>
默认情况下,所有资源都是共享的。通常XAML处理器创建一个已定义资源的实例,例如DataTemplate
并重用它。但是,如果资源直接添加到对象图中,并且由于默认情况下XAML处理器总是创建资源的单个实例并在整个范围内共享它,因此该实例只能成为XAML对象图的一部分一次。
换句话说,直接添加到对象图(视觉树或FrameworkElement
的情况下也是逻辑树)的Visual
的实例不能同时在此图中的多个位置。
必须通过在元素上设置x:Shared
属性为false
来显式禁用共享。这迫使XAML处理器为对象图中的每个出现创建资源的新实例:
<Viewbox x:Key="IconTrash" x:Shared="False">
<Canvas Width="24" Height="24">
<Path Data="M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z" Fill="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType=Button}}" />
</Canvas>
</Viewbox>