WPF Ribbon: DataTemplate causes BindingExpression path error

半世苍凉 提交于 2019-12-06 03:38:45

问题


I've run into a small problem using the WPF RibbonControl (October 2010 version). My idea was to bind the ItemsSource property of a RibbonGroup to my viewmodel, and use a DataTemplate to create RibbonButtons as needed. This works, but it causes a binding error (one for each button) when you show the window:

System.Windows.Data Error: 40 : BindingExpression path error: 'IsDropDownOpen' property not found on 'object' ''RibbonContentPresenter' (Name='PART_ContentPresenter')'. BindingExpression:Path=IsDropDownOpen; DataItem='RibbonContentPresenter' (Name='PART_ContentPresenter'); target element is 'RibbonButton' (Name=''); target property is 'NoTarget' (type 'Object')

Here is a code fragment, the viewmodel is replaced by an array of strings, but the issue is the same:

<ribbon:RibbonWindow x:Class="WpfRibbonApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ribbon="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        Title="MainWindow" x:Name="RibbonWindow" Width="640" Height="480" >

    <ribbon:RibbonWindow.Resources>
        <x:Array x:Key="buttonArray" Type="sys:String">
            <sys:String>Button 1</sys:String>
            <sys:String>Button 2</sys:String>
            <sys:String>Button 3</sys:String>
            <sys:String>Button 4</sys:String>
            <sys:String>Button 5</sys:String>
            <sys:String>Button 6</sys:String>
        </x:Array>
        <DataTemplate x:Key="buttonTemplate">
            <ribbon:RibbonButton Label="{Binding}"  />
        </DataTemplate>        
    </ribbon:RibbonWindow.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <ribbon:Ribbon>
            <ribbon:RibbonTab Header="Tab1">
                <ribbon:RibbonGroup Header="Group1"
                    ItemsSource="{StaticResource buttonArray}" 
                    ItemTemplate="{StaticResource buttonTemplate}"
                />
            </ribbon:RibbonTab>
        </ribbon:Ribbon>         
    </Grid>
</ribbon:RibbonWindow>

Again, it works, but the binding error is a bit annoying. Is there any way to get rid of it?


回答1:


The binding error is in the control template for the RibbonButton within the RibbonControlsLibrary. The style has the following MultiDataTrigger defined and is used when the RibbonButton is used as part of another control, like the RibbonSplitButton.

<MultiDataTrigger>
    <MultiDataTrigger.Conditions>
        <Condition Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsDropDownOpen}" Value="True" />
        <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled}" Value="False" />
        <Condition Binding="{Binding Path=HighContrast, Source={x:Static shell:SystemParameters2.Current}}" Value="True" />
    </MultiDataTrigger.Conditions>
    <Setter TargetName="OuterBorder" Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}" />
</MultiDataTrigger>



回答2:


I have Styled the RibbonButton with a ControlTemplate and without the MultiDataTrigger as below: This will not caused the binding errors.

<ribbon:RibbonWindow.Resources>

    <ControlTemplate x:Key="RibbonButtonTemplate" TargetType="{x:Type ribbon:RibbonButton}">
        <Grid x:Name="MainGrid" SnapsToDevicePixels="True">

            <Border x:Name="OuterBorder"
                CornerRadius="{TemplateBinding CornerRadius}"
                Background="{TemplateBinding Background}"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}" 
                Margin="1,1,1,1"/>

            <Border x:Name="MiddleBorder"
                CornerRadius="{TemplateBinding CornerRadius}"
                Background="Transparent"
                BorderBrush="Transparent"
                BorderThickness="{TemplateBinding BorderThickness}" >
                <Border x:Name="InnerBorder"
                    Background="Transparent"
                    BorderBrush="Transparent"
                    BorderThickness="{TemplateBinding BorderThickness}"
                    Padding="{TemplateBinding Padding}"
                    CornerRadius="{TemplateBinding CornerRadius}">
                    <StackPanel x:Name="StackPanel"
                            HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                            VerticalAlignment="{TemplateBinding VerticalContentAlignment}">

                        <Image x:Name="PART_Image"
                           Source="{TemplateBinding LargeImageSource}"
                           Margin="{DynamicResource {ComponentResourceKey TypeInTargetAssembly={x:Type ribbon:Ribbon}, 
                            ResourceId=LargeImageMargin}}"
                           RenderOptions.BitmapScalingMode="NearestNeighbor"
                           VerticalAlignment="Center"
                           HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" />

                        <Grid x:Name="GridText"
                          VerticalAlignment="Center"
                          HorizontalAlignment="Center">

                            <ribbon:RibbonTwoLineText x:Name="TwoLineText"
                                    Text="{TemplateBinding Label}"
                                    TextAlignment="Center"
                                    VerticalAlignment="Top"
                                    HorizontalAlignment="Center"
                                    LineHeight="13px"
                                    LineStackingStrategy="BlockLineHeight"
                                    HasTwoLines="{TemplateBinding ribbon:RibbonTwoLineText.HasTwoLines}"
                                    PathData="{TemplateBinding ribbon:RibbonTwoLineText.PathData}"
                                    PathFill="{TemplateBinding Foreground}"
                                    Margin="1,1,1,0" />
                        </Grid>
                    </StackPanel>
                </Border>
            </Border>


        </Grid>

        <ControlTemplate.Triggers>

            <!-- Large Variant -->
            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=ControlSizeDefinition.ImageSize}" Value="Large">
                <Setter Property="MinWidth" Value="44"/>
                <Setter Property="Height" Value="66"/>
                <Setter TargetName="GridText" Property="MinHeight" Value="26" />
                <Setter TargetName="TwoLineText" Property="HasTwoLines" Value="True" />
            </DataTrigger>

            <!-- Medium or Small Variant -->
            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=ControlSizeDefinition.ImageSize}" Value="Small">
                <Setter Property="Height" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SmallImageSource}"/>
                <Setter TargetName="StackPanel" Property="HorizontalAlignment" Value="Left" />

                <Setter TargetName="PART_Image" Property="Margin" Value="2,2,2,2" />
                <Setter TargetName="PART_Image" Property="Source" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SmallImageSource}" />
                <Setter TargetName="PART_Image" Property="Width" Value="16" />
                <Setter TargetName="PART_Image" Property="Height" Value="16" />
                <Setter TargetName="PART_Image" Property="HorizontalAlignment" Value="Left" />

                <Setter TargetName="TwoLineText" Property="HorizontalAlignment" Value="Left" />
                <Setter TargetName="TwoLineText" Property="Margin" Value="1" />
                <Setter TargetName="StackPanel" Property="Orientation" Value="Horizontal" />
            </DataTrigger>


            <!-- IsMouseOver -->
            <Trigger Property="IsMouseOver" Value="True">
                <Setter TargetName="OuterBorder" Property="Background" 
                        Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=MouseOverBackground}" />
                <Setter TargetName="OuterBorder" Property="BorderBrush" 
                        Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=MouseOverBorderBrush}" />
                <Setter TargetName="InnerBorder" Property="BorderBrush"
                        Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=FocusedBorderBrush}" />
            </Trigger>

            <!-- IsFocused -->
            <Trigger Property="IsKeyboardFocused" Value="True">
                <Setter TargetName="OuterBorder" Property="Background" 
                        Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=FocusedBackground}" />
                <Setter TargetName="OuterBorder" Property="BorderBrush" 
                        Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=FocusedBorderBrush}" />
                <Setter TargetName="InnerBorder" Property="BorderBrush" 
                        Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=FocusedBorderBrush}"/>
            </Trigger>

        </ControlTemplate.Triggers>
    </ControlTemplate>

    <Style x:Key="RibbonButtonStyle" TargetType="{x:Type ribbon:RibbonButton}" >
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="BorderBrush" Value="Transparent" />
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="CornerRadius" Value="2" />
        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
        <Setter Property="HorizontalContentAlignment" Value="Center" />
        <Setter Property="VerticalContentAlignment" Value="Center" />
        <Setter Property="MouseOverBorderBrush" Value="{Binding RelativeSource={RelativeSource Self},Path=Ribbon.MouseOverBorderBrush}" />
        <Setter Property="MouseOverBackground" Value="{Binding RelativeSource={RelativeSource Self},Path=Ribbon.MouseOverBackground}" />
        <Setter Property="PressedBorderBrush" Value="{Binding RelativeSource={RelativeSource Self},Path=Ribbon.PressedBorderBrush}" />
        <Setter Property="PressedBackground" Value="{Binding RelativeSource={RelativeSource Self},Path=Ribbon.PressedBackground}" />
        <Setter Property="FocusedBorderBrush" Value="{Binding RelativeSource={RelativeSource Self},Path=Ribbon.FocusedBorderBrush}" />
        <Setter Property="FocusedBackground" Value="{Binding RelativeSource={RelativeSource Self},Path=Ribbon.FocusedBackground}" />
        <Setter Property="Template" Value="{StaticResource RibbonButtonTemplate}" />
        <Setter Property="QuickAccessToolBarControlSizeDefinition">
            <Setter.Value>
                <ribbon:RibbonControlSizeDefinition ImageSize="Small" IsLabelVisible="False" />
            </Setter.Value>
        </Setter>

    </Style>

    <x:Array x:Key="buttonArray" Type="sys:String">
        <sys:String>Button 1</sys:String>
        <sys:String>Button 2</sys:String>
        <sys:String>Button 3</sys:String>
        <sys:String>Button 4</sys:String>
        <sys:String>Button 5</sys:String>
        <sys:String>Button 6</sys:String>
    </x:Array>
    <DataTemplate x:Key="buttonTemplate">
        <ribbon:RibbonButton Label="{Binding}" 
                             Style="{StaticResource ResourceKey=RibbonButtonStyle}" />
    </DataTemplate>


</ribbon:RibbonWindow.Resources>


来源:https://stackoverflow.com/questions/4276010/wpf-ribbon-datatemplate-causes-bindingexpression-path-error

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!