WPF XAML 资源对象仅可见一次
Posted
技术标签:
【中文标题】WPF XAML 资源对象仅可见一次【英文标题】:WPF XAML Resource Object Is Only Visible Once 【发布时间】:2021-10-31 00:57:47 【问题描述】:尝试了几个小时都没有成功,很想知道为什么三个按钮中只有一个显示图标 ViewBox 内容。
我觉得我对控件模板的内部工作了解不够。
第一个文件 ButtonProperties 类是包含 Icon ViewBox 的附加属性的所有者。 第二个文件是我的 MainWindow.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>
【问题讨论】:
【参考方案1】:默认情况下所有资源都是共享的。通常 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>
【讨论】:
非常感谢,救了我剩下的头发;) 好好照顾他们。至少为严重的问题节省几缕头发。一般来说,建议在头上的某个地方抓一把。以上是关于WPF XAML 资源对象仅可见一次的主要内容,如果未能解决你的问题,请参考以下文章