Why does data binding to DynamicResource not work? - wpf

The following code does not work. How do I make it work?
<Image Source="{DynamicResource {Binding VM.ImageKey}}" />

This is an incorrect usage of the DynamicResource MarkupExtension. Correct it would be:
<Image Source="{DynamicResource VM.ImageKey}" />
Assuming you have a resource with a key "VM.ImageKey" defined somewhere like this:
<Bla.Resources>
<BitmapImage x:Key="VM.ImageKey" UriSource="C:\Uri\To\Image.jpg" />
</Bla.Resources>
However if you want to bind against some property form the current DataContext you must not use DynamicResource but Binding:
<Image Source="{Binding VM.ImageKey}" />
Assuming your current DataContext is an instance that has a property called VM wich again has a property called ImageKey wich is a derived type of ImageSource.

This behaviour is by design. Binding works only on dependency properties of dependency objects and MarkupExtension is not dependency object.

It cannot work since the DyamicResource is a MarkupExtension and not a dependency property. Databinding only works with dependendcy properties.
However, there is a semi smooth workaround. Create a DynamicTextBlock class that extends a TextBlock.
The xaml:
<TextBlock x:Class="Rebtel.Win.App.Controls.DynamicTextBlock"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"/>
The codebehind:
public partial class DynamicTextBlock : TextBlock
{
public static readonly DependencyProperty TextKeyProperty = DependencyProperty.Register(
"TextKey", typeof(string), typeof(DynamicTextBlock), new PropertyMetadata(string.Empty, OnTextKeyChanged));
private static void OnTextKeyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var me = ((DynamicTextBlock)d);
if (e.NewValue != null)
{
me.TextKey = (string) e.NewValue;
}
}
public string TextKey
{
set { SetResourceReference(TextProperty, value); }
}
public DynamicTextBlock()
{
InitializeComponent();
}
}
Usage:
<local:DynamicTextBlock TextKey="{Binding TextKeyProperty}" />
The TextKeyProperty then returns a key that can be found in the ResourceDictionary. The same approach can be taken for an Image and its Source property.

If you want to specify the resource key dynamically you should specify it using the ResourceKey markup extension - not sure if it supports bindings in the way you want it to however. See here for more details.

I'm assuming that in this case, VM.ImageKey refers to a property on a data source whose value you wish to use as a resource dictionary key. The idea being that your data source can determine which image is used by supplying a resource key. (Most of the other answers on this page are unhelpful, because they have unfortunately missed what you're trying to do, assume that you want to use the literal text "VM.ImageKey" as a resource key, which I'm pretty sure isn't what you're asking for.)
This doesn't seem to be supported, but there's another approach that can enable you to select an image resource through a key determined by databinding: https://stackoverflow.com/a/20566945/497397

Related

Get instance of another element via Xaml Binding (Attached or DependencyProperty)

I have a use case where I want to get at a reference to an element in Xaml from another element.
For instance, consider this simplistic case. I have a UserControl called A and a UserControl called B,
and somehow I want to register an attached property where B can get the reference to A.
e.g.
<MyCustomControl Name="A"/>
<MyCustomControl Name="B"
AttachedPropClass.TheOtherControl="{Binding ElementName=A}"/>
So I would expect B.TheOtherControl to be equal to A. Is this possible in Xaml? Note I am not binding to a property of A, but rather I want the whole element.
Any solution using DependencyProperties, or AttachedProperties or Behaviors that lets me do this in Xaml would be great.
Edit: I'm attempting to do this in both WPF and Silverlight4. I have tried the above and it doesn't work, a property changed callback on the Attached property never gets hit.
You could use a Behaviour with a property that you set to the Control name and then search the logical Tree for the control. I have a similar thing where I want a certain event on one control to move focus to another control. I do this by specifying the control name to the Behaviour.
<TextBox Name="A"/>
<TextBox Name="B">
<Interactivity:Interaction.Behaviors>
<Behaviours1:ProgressNextOnEnterAction NextTextBoxControlName="A" />
</Interactivity:Interaction.Behaviors>
</TextBox>
Ok I think I figured out what happened.
Declare your dependency property like this:
private static readonly DependencyProperty TheOtherControlProperty =
DependencyProperty.RegisterAttached(
"TheOtherControl",
typeof(MyCustomControl),
typeof(AttachedPropClass),// Change this part
null);
public static MyCustomControlGetTheOtherControl(MyCustomControltarget)
{
return (MyCustomControl)target.GetValue(TheOtherControlProperty);
}
public static void SetTheOtherControl(MyCustomControltarget, TextBlock value)
{
target.SetValue(TheOtherControlProperty, value);
}
I think the issue is that you set the OwnerType of the Dependency Property to MyCustomControl instead of to AttachedPropClass.
I've created an example that works.
Give this a try and let me know if I'm right.
u_u

Silverlight: How to add a Dependency Property to multiple controls?

Is it possible to create a Dependency Property for multiple controls without resorting to subclass every one of it?
I thought about using Attached Properties but they nest only one level deep as far as I understand it.
I want something like this to be possible:
<!-- MyDataGrid implements the new Attached Properties SourceData and TargetData -->
<MyDataGrid>
<StackPanel>
<TextBox MyDataGrid.SourceData="{Binding Somewhere}" MyDataGrid.TargetData="{Binding Somewhere}" />
</StackPanel>
<CheckBox MyDataGrid.SourceData="{Binding Somewhere}" MyDataGrid.TargetData="{Binding Somewhere}" />
</MyDataGrid>
This won't work since the Attached Properties wouldn't be found in the TextBox since it's no direct descendent of MyDataGrid.
Background is that I try to automatically convert an old Xaml-like Gui-syntax into real Xaml and with the old system it was possible to set different sources and targets for changed data. Now I'm searching for a Xaml-solution that doesn't involve subclassing every control there is.
Thanks in advance.
are you sure you are using Attached property correctly?
public static readonly DependencyProperty SourceDataProperty = DependencyProperty.RegisterAttached(
"SourceData", typeof (string), typeof (MyDataGrid), new PropertyMetadata("test"));
public static void SetSourceData(DependencyObject obj, string sourceData)
{
obj.SetValue(SourceDataProperty, sourceData);
}
public static string GetSourceData(DependencyObject obj)
{
return (string) obj.GetValue(SourceDataProperty);
}
This worked for me.Though SetSourceData was not get called, but data was there.
To retrive data.
MyDataGrid.GetSourceData(tbox);
Where tbox is the instance of your TextBox.

What are the scenarios in which we need to use dependency property in WPF?

We can achieve the binding by simply CLR property, so why do we need to use DP?
When do you need DPs over CLRPs?
When you need binding
when you need property value change callback (Default Implementation)
When you need property value validation
When you need animation
When you need property value inheritance
When you need to attach a property value to another element (Attached Property, but still)
When you need styling
Some of these can be implemented in CLR properties. But, with DPs, its piece of cake.
Typically these are declared in UserControls and derived controls.
You can bind to a CLR property, but you can't bind with a CLR property; you'll need a dependency property to do any binding.
Edit (in response to comment)
Let's say you need a TextBox, but you want to customize it to have different behaviour in "EditMode" and "ReadMode". You'll need to either create a derived class or a UserControl; in either case you'll add a DependencyPropery.
public class TextBoxWithModes : TextBox
{
public bool EditMode
{
get { return (bool) GetValue(EditModeProperty); }
set { SetValue(EditModeProperty, value); }
}
public static readonly DependencyProperty EditModeProperty = DependencyProperty.Register(
"EditMode", typeof (bool), typeof (TextBoxWithModes));
}
With this in place, you can declare it in XAML:
<Namespace:TextBoxWithModes Text="enter text here"
Width="200"
HorizontalAlignment="Center"
EditMode="{Binding IsChecked, ElementName=editModeCheckBox}" />

WPF - Dependency Properties Error

I'm working on a WPF project, and my intention is to make two specific RadioButtons alter properties of another specified Component. But for now, i'm just trying to store a String inside the RadioButton.
For that, I've created a behavior class:
public class AdjustBehavior : Behavior<RadioButton>
{
With this property:
public static DependencyProperty AdjustLabelContentProperty =
DependencyProperty.RegisterAttached("LabelContent", typeof(String), typeof(AdjustBehavior),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.Inherits));
And these getters and setters:
public static String GetLabelContent(RadioButton tb)
{
return (String)tb.GetValue(AdjustLabelContentProperty);
}
public static void SetLabelContent(RadioButton tb, String value)
{
tb.SetValue(AdjustLabelContentProperty, value);
}
On the XAML side, I did this:
<RadioButton Content="Banana" Height="16" HorizontalAlignment="Left" Margin="30,216,0,0" Name="radioButton1" VerticalAlignment="Top" GroupName="a" IsThreeState="False" IsChecked="True" Checked="radioButton1_Checked" >
<int:Interaction.Behaviors>
<i:AdjustBehavior LabelContent="Apple" />
</int:Interaction.Behaviors>
</RadioButton>
Where int: is the namespace to Interaction.Behaviors and i: is the namespace to the AdjustBehavior class. But whenever I start my application, LabelContent is set to null. Why?
I didn't post the rest of my Behavior class because I think it won't matter, but I'll do if necessary.
Thanks in Advance.
Clark
You should use DependencyProperty.Register, not RegisterAttached. This isn't being used as an attached property, but rather a standard dependency property.
Attached property requires target to be attached to. In your case that target is radio button,
so you should use
<RadioButton i:AdjustBehavior.LabelContent="Apple" ... />
If you need to just create property of AdjustBehavior, use normal dependency property, not attached.
LabelContent should be either an attached property on RadioButton or dependency property on AdjustBehavior .

UserControl vs SurfaceWindow

I am trying to use values i declare inside a UserControl class to change things inside the SurfaceWindow class. Now what i know so far is that i have to use a DependencyProperty to get the value from the UserControl and then put it inside a public string.
public string MapValue
{
get { return (string)GetValue(MapValueProperty); }
set { SetValue(MapValueProperty, value); }
}
public static readonly
DependencyProperty MapValueProperty = DependencyProperty.Register("MapValue", typeof(string), typeof(MapManager));
Now my question is, how do i bind the public string (that is inside the UserControl) to a element (inside the SurfaceWindow)?
If i use the DependencyProperty do i make a new class or do i put it in the usercontrol code?
I would be very happy if someone could help me with this problem..
As far as i can tell you are trying to bind to a dependency property of some control in your window.
If this is the case you could use the ElementName syntax in the binding declarations such as:
<TextBlock Text="{Binding ElementName=MapControl, Path=MapValue}"/>
I had already have this inside my window control:
<Image x:Name="iGroundPlan" Source="{Binding ElementName=MapManager,Path=MapValue}" />
(MapManager is the name of my usercontrol)
But looks like it aint working, and i dont know why.. Its like the windows never knows when the value MapValue is updated in my usercontrol =\

Resources