开发者

ToolBar item DataTemplate binding RelativeSource search failing to find parent ToolBar

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开发者_Python百科>
            </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?

 public static readonly DependencyProperty IconSizeProperty = 
    DependencyProperty.RegisterAttached( "IconSize", typeof(double), typeof(ToolBar ),
        new FrameworkPropertyMetadata(32, FrameworkPropertyMetadataOptions.Inherits));

public static double GetIconSize(DependencyObject target)
{
    return (double)target.GetValue(IconSizeProperty);

}

public static void SetIconSize(DependencyObject target, double value)
{
    target.SetValue(IconSizeProperty, value);
}

Then you can just access the IconSize like

<Button.Content>
                <Image 
                    Width="{Binding RelativeSource={RelativeSource Self}, ctrls::ToolBar.IconSize}" 
                    Height="{Binding Path=Width,RelativeSource={RelativeSource Self}}" 
                    Source="{Binding Path=MetaData, 
                    Converter={StaticResource IconMetaDataToImageConverter},
                    ConverterParameter={StaticResource IconToImageConverterParameter}}"/>

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.


The DataTemplate looks like it is being defined inside a DataTemplateSelector declaration, which isn't part of the Visual Tree, and so won't be able to navigate up from there if the Binding were being evaluated in that spot. Where is the template actually being applied?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜