Dynamic binding to a "Path" of the resource
Asked Answered
B

1

6

First the code what I was starting from:

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

While this binding is compiling and running fine the reason I am not satisfied is that imageSource changes during runtime.

StaticResource Markup Extension: Provides a value for any XAML property attribute by looking up a reference to an already defined resource. Lookup behavior for that resource is analogous to load-time lookup, which will look for resources that were previously loaded from the markup of the current XAML page as well as other application sources, and will generate that resource value as the property value in the run-time objects.

Since imageSource value changing during runtime I had to change StaticResource to DynamicResource. But the property Source is not a dependency property and thus the following code will raise a runtime error:

SmallImageSource="{Binding Source={DynamicResource imageSource},
                   Path=Source,
                   UpdateSourceTrigger=LostFocus}

For that reason I need to bind the dynamic resource directly to SmallImageSource, which is a dependency property:

SmallImageSource="{DynamicResource imageSource}"

This again will raise a runtime error because imageSource is type of Image. SmallImageSource expects the value to be type of ImageSource.

One might suggest now to set the data context to my dynamic resource and bind the property appropriately. If I do so, I'd kill the binding of property IsEnabled which has another DataContext.

And as far as I know, MultiBinding is also not a solution since this provides a mechanism to bind a property against several sources but does not provide binding different properties against different contexts and sources.

While thinking about how to get on, it came to my mind that luckily I can move the ImageSource rigmarole into a IValueConverter. In the given data context of my RibbonMenuButton I have a string value with the appropriate value which is actually also the source of my ImageSource.

Anyway, I still wondering how I would solve the problem if I hadn't the other approach, i.e. if both sources were in different data contexts. Is there anything what I am not seeing? How can I ensure not to kill the other binding by overwriting the DataContext and though binding against a property of a dynamic resource?


The imageSource is pretty the same as the XAML example on the DrawingImage msdn page.

<Image x:Key="imageSource">
  <Image.Source>
    <DrawingImage>
...
Berthaberthe answered 26/3, 2013 at 9:57 Comment(1)
Can you post the code where you define the "imageSource" resource?Andeee
A
1

You might try defining "imageResource" as an ImageSource instead of an Image. This works for me.

<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>

Also, you could set the DataContext of your RibbonMenuButton without overriding IsEnabled by using an ElementName binding as follows.

<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>
Andeee answered 26/3, 2013 at 20:14 Comment(3)
I think the second idea could work. Will try that tomorrow. The first idea, however, will not work. I forgot to mention that I paint the image myself, there's not image to link to.Berthaberthe
@Berthaberthe Regarding the first idea, you could update the imageSource key of the resource dictionary on the fly if you had access to it from the code that paints your images.Andeee
I just tested the second approach. For some reason it didn't work for me with ElementName but with RelativeSource. - I paint the image in XAML, I updated the question regarding that. I didn't debug into the issue that when ImageSource is directly being used (instead of Image.Source) content cannot be added.Berthaberthe

© 2022 - 2024 — McMap. All rights reserved.