プロフィール

髭山髭人(ひげひと)

自分の書いた記事が、一人でも誰かの役に立てば...
活動信条の一つとして「貴方のメモは、誰かのヒント」というのがあります。

このサイトについて

本家HP packetroom.net から切り離した いわゆる技術メモ用のブログで、無料レンタルサーバーにて運用しています。広告表示はその義務なのでご容赦。
XREA さんには長年お世話になっています

C# WPF System.Windows.Data Error: 4 の Binding Error メモ

ざっくり

C# WPF で System.Windows.Controls.MenuItem のレイアウトデザインを xaml 連携で弄ってたら
Binding Error が出てきたのでちょっとだけ掘り下げたメモ

MenuItem 用に、独自 System.Windows.Style を組んで割り当てていた事(だけ)が原因かと思ったけど、
どうやらそれだけでも無い…らしい? あまり掘り下げてないので適当な書き散らしです

コード類

App.xaml 側 リソース定義 抜粋 ( 長めの定義は 記事後半に載せました )

<Style x:Key="EditSubMenuitem" TargetType="{x:Type MenuItem}">
    <Setter Property="VerticalContentAlignment" Value="Stretch"/>
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <!-- 以下クソ長いので省略 -->
</Style>

今回ベースとなる コードビハインド側

Style _editSubMenuiItemStyle = (Style)(App.Current.Resources["EditSubMenuitem"]);
System.Windows.Controls.MenuItem _menuItem = new MenuItem();
// 以下、プロパティとか弄ったり、
// コントロールとかに突っ込んで HogeHogeしたい

出てきたエラー文言

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''. BindingExpression:Path=HorizontalContentAlignment; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'HorizontalContentAlignment' (type 'HorizontalAlignment')

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''. BindingExpression:Path=VerticalContentAlignment; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'VerticalContentAlignment' (type 'VerticalAlignment')

自環境でのとりあえず解決ムーブ

おま環 は否めない
順番を弄るとよさそう?

▼ 最速で MenuItem.Style に割り当てから他プロパティを弄る

エラーなし

MenuItem _menuItem = new MenuItem();
_menuItem.Style = _editSubMenuiItemStyle;
_menuItem.Header = "ほげほげ";

エラーあり

MenuItem _menuItem = new MenuItem();
_menuItem.Header = "ほげほげ";
_menuItem.Style = _editSubMenuiItemStyle;

▼ 手付でプロパティ割り当て

エラーなし

MenuItem _menuItem = new MenuItem();
_menuItem.Header = "ほげほげ";
_menuItem.VerticalContentAlignment = VerticalAlignment.Center;
_menuItem.HorizontalContentAlignment = System.Windows.HorizontalAlignment.Stretch;
_menuItem.Style = _editSubMenuiItemStyle;

エラーあり

MenuItem _menuItem = new MenuItem();
_menuItem.Header = "ほげほげ";
_menuItem.Style = _editSubMenuiItemStyle;
_menuItem.VerticalContentAlignment = VerticalAlignment.Center;
_menuItem.HorizontalContentAlignment = System.Windows.HorizontalAlignment.Stretch;

これは?

▼ コードビハインドは下記の順序固定で、xaml 側の2プロパティ記述を削った動作差分

MenuItem _menuItem = new MenuItem();
_menuItem.Style = _editSubMenuiItemStyle;
_menuItem.Header = "ほげほげ";

エラーなし

<Style x:Key="EditSubMenuitem" TargetType="{x:Type MenuItem}">
    <Setter Property="VerticalContentAlignment" Value="Stretch"/>
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <!-- 以下略 -->
</Style>

削るとエラー出る

<Style x:Key="EditSubMenuitem" TargetType="{x:Type MenuItem}">
    <!--Setter Property="VerticalContentAlignment" Value="Stretch"/-->
    <!--Setter Property="HorizontalContentAlignment" Value="Center"/-->
    <!-- 以下略 -->
</Style>

App.xaml 側

本ケースで利用していた System.Windows.Controls.MenuItem 用の System.Windows.Style です。

雑ですんまそん
見てると頭痛くなってくる;;

<Application.Resources>

    <Style x:Key="EditSubMenuitem" TargetType="MenuItem">
        <Setter Property="FontSize" Value="20"/>
        <Setter Property="VerticalContentAlignment" Value="Stretch"/>
        <Setter Property="HorizontalContentAlignment" Value="Center"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="MenuItem">
                    <Border x:Name="templateRoot" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                        <Grid VerticalAlignment="Center">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                            </Grid.ColumnDefinitions>
                            <ContentPresenter x:Name="Icon"  Content="{TemplateBinding Icon}" ContentSource="Icon" HorizontalAlignment="Center" Height="16" Margin="0,0,0,0" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center" Width="16"/>
                            <Path x:Name="GlyphPanel" Data="F1M10,1.2L4.7,9.1 4.5,9.1 0,5.2 1.3,3.5 4.3,6.1 8.3,0 10,1.2z" Fill="{TemplateBinding Foreground}" FlowDirection="LeftToRight" Margin="3" Visibility="Collapsed" VerticalAlignment="Center"/>
                            <ContentPresenter TextElement.FontSize="12"  ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" Grid.Column="1" ContentStringFormat="{TemplateBinding HeaderStringFormat}" ContentSource="Header" Margin="2,0,7,0" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                            <Popup Grid.Column="1" x:Name="PART_Popup"  AllowsTransparency="True" Focusable="False" IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}" Placement="Right">
                                <Border x:Name="SubMenuBorder" BorderBrush="#FF999999" BorderThickness="1" Background="#FFF0F0F0" Padding="2">
                                    <ScrollViewer x:Name="SubMenuScrollViewer" Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
                                        <Grid RenderOptions.ClearTypeHint="Enabled">
                                            <Canvas HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
                                                <Rectangle x:Name="OpaqueRect" Fill="{Binding Background, ElementName=SubMenuBorder}" Height="{Binding ActualHeight, ElementName=SubMenuBorder}" Width="{Binding ActualWidth, ElementName=SubMenuBorder}"/>
                                            </Canvas>
                                            <Rectangle Fill="#FFD7D7D7" HorizontalAlignment="Left" Margin="29,2,0,2" Width="1"/>
                                            <ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Cycle" Grid.IsSharedSizeScope="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" KeyboardNavigation.TabNavigation="Cycle"/>
                                        </Grid>
                                    </ScrollViewer>
                                </Border>
                            </Popup>
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSuspendingPopupAnimation" Value="True">
                            <Setter Property="PopupAnimation" TargetName="PART_Popup" Value="None"/>
                        </Trigger>
                        <Trigger Property="IsChecked" Value="True">
                            <Setter Property="Visibility" TargetName="GlyphPanel" Value="Visible"/>
                            <Setter Property="Visibility" TargetName="Icon" Value="Collapsed"/>
                        </Trigger>
                        <Trigger Property="IsHighlighted" Value="True">
                            <Setter Property="Background" TargetName="templateRoot" Value="#3D26A0DA"/>
                            <Setter Property="BorderBrush" TargetName="templateRoot" Value="#FF26A0DA"/>
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter Property="TextElement.Foreground" TargetName="templateRoot" Value="#FF707070"/>
                            <Setter Property="Fill" TargetName="GlyphPanel" Value="#FF707070"/>
                        </Trigger>
                        <Trigger Property="CanContentScroll" SourceName="SubMenuScrollViewer" Value="False">
                            <Setter Property="Canvas.Top" TargetName="OpaqueRect" Value="{Binding VerticalOffset, ElementName=SubMenuScrollViewer}"/>
                            <Setter Property="Canvas.Left" TargetName="OpaqueRect" Value="{Binding HorizontalOffset, ElementName=SubMenuScrollViewer}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</Application.Resources>