I have a ToolBar containing Buttons, some of the Buttons have only an Image for content, others have only Text. I am trying to bind the width property of the Button Image to a custom Property on my derived ToolBar class. It works sometimes but fails other times with the following error:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='NuiWpfCore.Controls.ToolBar', AncestorLevel='1''. BindingExpression:Path=IconSize; DataItem=null; target element is 'Image' (Name=''); target property is 'Width' (type 'Double')
Here is the xaml containing the element binding that is failing. The DataTemplate is returned from a DataTemplateSelector which is created inline:
<pres:ToolBar x:Class="NuiWpfCore.Controls.ToolBar"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:pres="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:core="clr-namespace:NuiWpfCore"
xmlns:ctrls="clr-namespace:NuiWpfCore.Controls"
xmlns:select="clr-namespace:NuiWpfCore.Selectors"
xmlns:converters="clr-namespace:NuiWpfCore.Converters"
xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase">
<ToolBar.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/NuiWpfCore;component/Controls/MenuBarTemplate.xaml" />
</ResourceDictionary.MergedDictionaries>
<converters:ListPairToStringConverter x:Key="ListPairToStringConverter" />
<converters:IconMetaDataToImageConverter x:Key="IconMetaDataToImageConverter" />
<converters:IconMetaDataToImageConverterParameter x:Key="IconToImageConverterParameter"
ConvertToImage="False" Width="16" Height="16" />
</ResourceDictionary>
</ToolBar.Resources>
<ToolBar.ItemTemplateSelector>
<select:ToolBarItemDataTemplateSelector>
<!-- other DataTemplates omitted for brevity -->
<select:ToolBarItemDataTemplateSelector.IconCommand>
<DataTemplate DataType="{x:Type core:PropertyElement}">
<Button IsEnabled="{Binding Path=CanEdit}" Command="{Binding}">
<Button.Content>
<Image
Width="{Binding Path=IconSize,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ctrls:ToolBar}} }"
Height="{Binding Path=Width,
RelativeSource={RelativeSource Self}}"
Source="{Binding Path=MetaData,
Converter={StaticResource IconMetaDataToImageConverter},
ConverterParameter={StaticResource IconToImageConverterParameter}}"/>
</Button.Content>
</Button>
</DataTemplate>
</select:ToolBarItemDataTemplateSelector.IconCommand>
<!-- other DataTemplates omitted for brevity -->
</select:ToolBarItemDataTemplateSelector>
</ToolBar.ItemTemplateSelector>
</pres:ToolBar>
Here is the ToolBar class with the Source Property for the binding.
public partial class ToolBar : System.Windows.Controls.ToolBar, Views.IView
{
public ToolBar() : base()
{
InitializeComponent();
IconSize = 32;
}
public int IconSize { get; set; }
}
This ToolBar class is sometimes used in a ToolBarTray and other times it is not, but the bind search fails in both cases in certain scenarios.
Does anybody have any ideas as to why this might be failing?
Have you considered making
IconSize
on your ToolBar an inherited property?Then you can just access the IconSize like
First you should set it on your toolbar, and every other element down the tree can access this property.
Sorry out of my head, not 100% guarenteed to be correct. But the overall idea of Value Inheritance is a good way to solve this.