The problem is clear. Dynamic resources are resolved by parsing upwards the logical tree. The dynamic resource is not found because your textblock is not in the correct logical tree, probably he does not have a logical parent and that is why the resource is not found.
You could solve it by adding it to the correct logical tree like for example it could be the child of the textbox. It is not so trivial and depends also on the usage that is required, because the customization of the logical tree is not so trivial.
There is not so simple like having a public method AddLogicalChild because then you would mess up the entire system. Now the question is who has the responsibility of doing this. The general solution could be to have a custom TextBox that overrides logical children related methods and returns also the watermark textblock.
It is not the global solution but in your case you could have a custom textbox overriding the LogicalChildren property like this:
public class WaterTextBox : TextBox
{
protected override IEnumerator LogicalChildren
{
get
{
ArrayList list = new ArrayList();
list.Add(WatermarkService.GetWatermark(this));
return (IEnumerator)list.GetEnumerator();
}
}
}
Remember this is just a workaround and this way would work only on your custom textboxes with dynamic resources.
Also it is not the correct implementation because you should add the watermark to the other logical children not ignore the other logical children and have only the watermark which is not even checked for null like this:
public class WaterTextBox : TextBox
{
protected override IEnumerator LogicalChildren
{
get
{
ArrayList list = new ArrayList();
IEnumerator enumerator = base.LogicalChildren;
while (enumerator.MoveNext())
{
list.Add(enumerator.Current);
}
object watermark = WatermarkService.GetWatermark(this);
if (watermark != null && !list.Contains(watermark))
{
list.Add(WatermarkService.GetWatermark(this));
}
return (IEnumerator)list.GetEnumerator();
}
}
}
To make it more general you should define an interface like IWatermark defining a property like IsWaterMarkAdded which will be implemented by your custom TextBox and ComboBox and will be used by the watermark service. The LogicalChildren override will check for the value of this property. This way you can extend functionality for your TextBox and ComboBox but still it is not an extensible solution for any control.