WPF XAML 资源对象仅可见一次
WPF XAML Resource Object Is Only Visible Once
尝试了几个小时都没有成功,很想知道为什么三个按钮中只有一个显示图标 ViewBox 内容。
我觉得我对控件模板的内部工作原理还不够了解。
第一个文件 ButtonProperties class 是包含 Icon ViewBox 的附件 属性 的所有者。
第二个文件是我的 MainWindow.xaml Window,它应该显示 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>
尝试了几个小时都没有成功,很想知道为什么三个按钮中只有一个显示图标 ViewBox 内容。
我觉得我对控件模板的内部工作原理还不够了解。
第一个文件 ButtonProperties class 是包含 Icon ViewBox 的附件 属性 的所有者。 第二个文件是我的 MainWindow.xaml Window,它应该显示 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>