【问题标题】:Style to change images on buttons in dialog样式以更改对话框中按钮上的图像
【发布时间】:2021-01-26 03:35:51
【问题描述】:

我无法让以下工作,我一定错过了一些基本的东西。 我的目标是在对话框(窗口)上有一种样式,以便在其中的按钮上设置图像。 所以我在对话框代码中添加了一个 DependencyProperty,如下所示:

public static readonly DependencyProperty ImageRefreshProperty =
  DependencyProperty.Register(nameof(ImageRefreshProperty), typeof(ImageSource),
    typeof(MyDlg), new PropertyMetadata(new BitmapImage(
      new Uri(@"pack://application:,,,/component/Resources/refresh.png"))));
public ImageSource ImageRefresh {
  get { return (ImageSource)GetValue(ImageRefreshProperty); }
  set { SetValue(ImageRefreshProperty, value); }
}

在 Xaml 我有这个:

<Button DockPanel.Dock="Left" Style="{StaticResource buttonIcon}">
  <Image Source="{Binding Path=ImageRefresh,
      RelativeSource={RelativeSource AncestorType=local:MyDlg}}" />
</Button>

只要我使用代码更改图像就可以正常工作,例如

dlg.ImageRefresh = new BitmapImage(
  new Uri("pack://application:,,,/component/Resources/refr.png"));

但理想情况下,我想通过一种样式设置图像,如下所示:

<Style TargetType="{x:Type MyDlg}">
  <Setter Property="ImageRefresh" Value="pack://application:,,,/component/Resources/refr.png" />
</Style>

我得到的错误是:

System.Windows.Markup.XamlParseException:
''Provide value on 'System.Windows.StaticResourceExtension' threw an exception.' 
Inner Exception System.Windows.Markup.XamlParseException:
ArgumentNullException: Key cannot be null. Arg_ParamName_Name 

我还尝试了一个在其中定义 BitmapImage 而不是字符串的 Setter Value,但我仍然得到同样的错误:

<Setter Property="ImageRefresh">
  <Setter.Value>
    <BitmapImage UriSource="pack://application:,,,/component/Resources/refr.png"/>
  </Setter.Value>
</Setter>

为 DependencyProperty 的 getter/setter 设置断点甚至不会被命中,在 Image 的 Source 的绑定上的 Converter 也不会。

我在这里错过了什么?

编辑:为了查看 ImageSource 是否与它有关,我用另一个 bool 类型的属性测试了我的代码?在对话框中设置按钮的 IsEnabled 属性,但结果是一样的。所以错误不在于图像,它的包 URL(顺便说一句),但显然与其他东西有关。

【问题讨论】:

  • 想知道 Pack URI 应该如何工作。您的 Visual Studio 项目中是否真的有顶级 /component 文件夹?如果不是,则 URI 应该是 pack://application:,,,/Resources/refr.pngpack://application:,,,/AssemblyName;component/Resources/refr.png
  • 您在哪里声明该样式?
  • 包 URI 不是问题。如前所述,通过代码设置图像时它工作得非常好,但尝试通过样式设置它会导致错误。我还用我用 bool 类型的属性做的另一个测试编辑了这个问题?而不是 ImageSource。
  • 样式设置在我用于许多其他事情的样式列表中(我简化了问题的代码,但它是大型代码库的一部分),并且对话框上设置了这种样式(实际上删除它不会有问题,但显然不会改变预期的属性)。

标签: wpf .net-5


【解决方案1】:

在对我的代码进行了一些挖掘之后,我自己找到了答案。问题是 DependencyProperty 的定义。 我的代码有:

public static readonly DependencyProperty ImageRefreshProperty =
  DependencyProperty.Register(nameof(ImageRefreshProperty) /*Wrong*/,
    typeof(ImageSource),
    typeof(MyDlg), new PropertyMetadata(new BitmapImage(
      new Uri(@"pack://application:,,,/component/Resources/refresh.png"))));

但应该是:

public static readonly DependencyProperty ImageRefreshProperty =
  DependencyProperty.Register(nameof(ImageRefresh) /*Correct*/,
    typeof(ImageSource),
    typeof(MyDlg), new PropertyMetadata(new BitmapImage(
      new Uri(@"pack://application:,,,/component/Resources/refresh.png"))));

一个很小的疏忽带来很大的后果......

【讨论】:

  • 从对话外部设置 DP 是否有效?从App.xaml 设置时,我仍然遇到错误。从代码隐藏或对话框标记设置的相同值没有问题。
  • 是的,它现在可以从样式中完美运行。
【解决方案2】:

内部异常 System.Windows.Markup.XamlParseException: ArgumentNullException:键不能为空。 Arg_ParamName_Name

根据错误消息,您的Style 上缺少x:Key

<Style x:Key="MyDialogStyle" TargetType="{x:Type MyDlg}">
    <Setter Property="ImageRefresh Value="..."/>
</Style>

根据this answer,如果您不想设置显式密钥,可以使用x:Key={x:Type MyDlg}"

<Style x:Key="{x:Type MyDlg}" TargetType="{x:Type MyDlg}">
    <Setter Property="ImageRefresh Value="..."/>
</Style>

【讨论】:

  • 恐怕不是这样。我为 SO 上的问题清理了一些代码,但实际上我的风格有一个关键,但我仍然得到错误。
  • 嗯,我正在复制。明天更新。
  • 我现在确定 string 设置器不起作用,因为 DependencyProperty 期待 ImageSource 但您已经发现了这一点。在我看来,setter/getter 从未被击中,因为框架在初始化期间对属性的默认值进行了一些验证。
  • 只要 TargetType 是唯一的,ResourceDictionary 中的样式就不需要x:Key。如果省略它,Key 将隐式设置为 TargetType。
  • 关于“字符串设置器”的评论也毫无意义。有从字符串到 ImageSource 等目标类型的内置类型转换。
猜你喜欢
  • 2020-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-01
  • 1970-01-01
  • 2011-01-28
  • 2023-04-03
  • 1970-01-01
相关资源
最近更新 更多