动态绑定到资源的“路径”

6

首先是我开始的代码:

<ribbon:RibbonMenuButton IsEnabled="{Binding ForegroundIsConfigurable}"
          SmallImageSource="{Binding Source={StaticResource imageSource},
                             Path=Source,
                             UpdateSourceTrigger=OnPropertyChanged}">

虽然这个绑定在编译和运行时都没有问题,但我不满意的原因是imageSource在运行时会发生变化。

StaticResource Markup Extension: 通过查找对已定义资源的引用为任何XAML属性提供值。该资源的查找行为类似于加载时查找,它将查找之前从当前XAML页面标记以及其他应用程序源中加载的资源,并将生成该资源值作为运行时对象的属性值。

由于imageSource的值在运行时发生了改变,所以我不得不将StaticResource更改为DynamicResource。但是Source属性不是依赖属性,因此以下代码将引发运行时错误:
SmallImageSource="{Binding Source={DynamicResource imageSource},
                   Path=Source,
                   UpdateSourceTrigger=LostFocus}

因此,我需要直接将动态资源绑定到依赖属性SmallImageSource

SmallImageSource="{DynamicResource imageSource}"

这会再次引发运行时错误,因为imageSource的类型是Image。而SmallImageSource需要该值的类型为ImageSource
有人可能建议现在将数据上下文设置为我的动态资源并适当地绑定属性。如果我这样做,就会破坏另一个DataContext中的IsEnabled属性绑定。
据我所知,MultiBinding也不是一种解决方案,因为它提供了一种将属性绑定到多个源的机制,但不提供将不同的属性绑定到不同的上下文和源的绑定。
在考虑如何继续之前,我想到幸运的是,我可以将ImageSource步骤移动到IValueConverter中。在我的RibbonMenuButton的给定数据上下文中,我有一个字符串值与适当的值,实际上也是我的ImageSource的源。
无论如何,我仍然在想,如果我没有其他方法,即如果两个源位于不同的数据上下文中,我将如何解决这个问题。是否有什么我没有注意到的东西?如何确保通过覆盖DataContext并尽管绑定到动态资源的属性而不破坏其他绑定? imageSourceDrawingImage msdn page上的XAML示例非常相似。
<Image x:Key="imageSource">
  <Image.Source>
    <DrawingImage>
...

你能否发布一下定义“imageSource”资源的代码呢? - Timothy Schoonover
1个回答

1
你可以尝试将 "imageResource" 定义为 ImageSource 而不是 Image。这对我有用。
<r:RibbonWindow
    x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:r="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"
    xmlns:pc="clr-namespace:System.Windows.Media;assembly=PresentationCore">
    <Grid>
        <Grid.Resources>
            <pc:ImageSource x:Key="imageSource">your_image.png</pc:ImageSource>
        </Grid.Resources>
        <r:Ribbon>
            <r:RibbonMenuButton
                IsEnabled="{Binding ForegroundIsConfigurable}"
                SmallImageSource="{DynamicResource imageSource}">
            </r:RibbonMenuButton>
        </r:Ribbon>
    </Grid>
</r:RibbonWindow>

此外,您可以使用元素名称绑定来设置RibbonMenuButton的DataContext,而无需覆盖IsEnabled。
<r:RibbonWindow x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:r="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"
        Title="MainWindow" Height="350" Width="525">

    <Grid x:Name="root">

        <Grid.Resources>
            <Image x:Key="imageSource" Source="{Binding myImageSource}"/>
        </Grid.Resources>

        <r:Ribbon>
            <r:RibbonMenuButton DataContext="{DynamicResource imageSource}"
                IsEnabled="{Binding ElementName=Root, Path=DataContext.ForegroundIsConfigurable}"
                SmallImageSource="{Binding Source}"/>
        </r:Ribbon>
    </Grid>
</r:RibbonWindow>

我认为第二个想法可能可行。明天会尝试一下。然而,第一个想法不可行。我忘了提到我自己绘制图像,没有可以链接的图像。 - Em1
关于第一个想法,如果您可以从代码中访问绘制图像的资源字典,您可以在运行时动态更新其imageSource键。 - Timothy Schoonover
我刚刚测试了第二种方法。由于某些原因,使用ElementName时它对我不起作用,但使用RelativeSource时可以。 - 我在XAML中绘制图像,我已经更新了相关问题。当直接使用ImageSource(而不是Image.Source)时,无法添加内容,我还没有深入调试这个问题。 - Em1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接