开发者

WPF Ribbon: DataTemplate causes BindingExpression path error

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"
   开发者_JS百科     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?


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>


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>
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜