CustomControl

时间:2017-10-19 14:51:24

标签: c# wpf xaml popup togglebutton

所以我在wpf中有以下xaml代码。这给了我一个DropdownButton的行为,就像我期望的那样。

<ToggleButton Content="Test"
                  VerticalAlignment="Center"
                  Focusable="False"
                  IsChecked="{Binding IsOpen, ElementName=Popup, Mode=TwoWay}"
                  Height="25"
                  Width="20"
                  x:Name="btn">
        <ToggleButton.Style>
            <Style TargetType="{x:Type ToggleButton}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsOpen, ElementName=Popup}" Value="True">
                        <Setter Property="IsHitTestVisible" Value="False" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ToggleButton.Style>
    </ToggleButton>

    <Popup Placement="Bottom"
           PlacementTarget="{Binding ElementName=btn}"
           x:Name="Popup"
           StaysOpen="False">
        <TextBlock Background="AliceBlue">Bla</TextBlock>
    </Popup>

现在,因为我使用了几次,所以我想创建一个自定义控件。

到目前为止,课程看起来像这样:

public class CustomDropdownButton : ToggleButton
{
    public static readonly DependencyProperty DropdownContentProperty = DependencyProperty.Register("DropdownContent", typeof(UIElement), typeof(CustomDropdownButton));

    static CustomDropdownButton()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomDropdownButton), new FrameworkPropertyMetadata(typeof(CustomDropdownButton)));
    }

    public UIElement DropdownContent
    {
        get
        {
            return (UIElement)GetValue(DropdownContentProperty);
        }
        set
        {
            SetValue(DropdownContentProperty, value);
        }
    }
}

我编辑了样式,它看起来像这样:

<Style x:Key="ButtonFocusVisual">
    <Setter Property="Control.Template">
        <Setter.Value>
            <ControlTemplate>
                <Rectangle StrokeDashArray="1 2" StrokeThickness="1" 
                           Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" 
                           SnapsToDevicePixels="true" Margin="2"/>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
    <GradientStop Color="#F3F3F3" Offset="0"/>
    <GradientStop Color="#EBEBEB" Offset="0.5"/>
    <GradientStop Color="#DDDDDD" Offset="0.5"/>
    <GradientStop Color="#CDCDCD" Offset="1"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="ButtonNormalBorder" Color="#FF707070"/>

<Style TargetType="{x:Type local:CustomDropdownButton}">
    <Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
    <Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/>
    <Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="Padding" Value="1"/>
    <Setter Property="ClickMode" Value="Press"/>
    <Setter Property="Focusable" Value="False"/>
    <Setter Property="IsChecked" Value="{Binding IsOpen, ElementName=Popup, Mode=TwoWay}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:CustomDropdownButton}">

                <themes:ButtonChrome x:Name="Chrome"
                                     BorderBrush="{TemplateBinding BorderBrush}"
                                     Background="{TemplateBinding Background}"
                                     RenderMouseOver="{TemplateBinding IsMouseOver}"
                                     SnapsToDevicePixels="true">
                    <StackPanel Orientation="Horizontal"
                                IsHitTestVisible="True">
                        <ContentPresenter Content="{TemplateBinding Content}"
                                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                          Margin="5,0,0,0"/>
                        <Path x:Name="ArrowPath"
                              Margin="7,3,3,2"
                              Fill="Gray"
                              Stroke="Gray"
                              StrokeThickness="1"
                              StrokeStartLineCap="Round"
                              StrokeEndLineCap="Round"
                              Stretch="Uniform"
                              VerticalAlignment="Center"
                              HorizontalAlignment="Center"
                              RenderTransformOrigin=".5,.5"
                              Data="M0,0 L2,0 L4,2 L5,3 L6,2 L8,0 L10,0 L8,2 L5,7 L2,2 z">
                            <Path.RenderTransform>
                                <RotateTransform Angle="-90"/>
                            </Path.RenderTransform>
                        </Path>

                        <Popup Placement="Bottom"
                               x:Name="Popup"
                               StaysOpen="False"
                               Child="{TemplateBinding DropdownContent}"/>
                    </StackPanel>
                </themes:ButtonChrome>

                <ControlTemplate.Triggers>
                    <DataTrigger Binding="{Binding IsOpen, ElementName=Popup}" Value="True">
                        <Setter Property="IsHitTestVisible" Value="False" />
                    </DataTrigger>
                    <Trigger Property="IsKeyboardFocused" Value="true">
                        <Setter Property="RenderDefaulted" TargetName="Chrome" Value="true"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Foreground" Value="#ADADAD"/>
                    </Trigger>
                    <Trigger Property="IsChecked" Value="False">
                        <Trigger.EnterActions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetName="ArrowPath"
                                                     Storyboard.TargetProperty="RenderTransform.(RotateTransform.Angle)"
                                                     To="-90"
                                                     Duration="0:0:0.2"/>
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.EnterActions>
                        <Trigger.ExitActions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetName="ArrowPath"
                                                     Storyboard.TargetProperty="RenderTransform.(RotateTransform.Angle)"
                                                     To="0"
                                                     Duration="0:0:0.2"/>
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.ExitActions>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

弹出按钮的示例代码工作得很好。 我想我会通过使用Setter将弹出窗口的IsOpen属性绑定到ToggleButton的IsChecked属性来获得相同的效果。

我是否缺少需要添加的触发器行为?我无法弄清楚为什么它不会打开。

通过删除IsChecked和ClickMode Setter修复它,从弹出窗口绑定IsOpen属性而不是使用templatebinding,但将建议的RelativeSource绑定到IsChecked,将Mode设置为TwoWay。保留了StaysOpen和DataTrigger。

由于我为ListView中的ListViewItem设置了边距,弹出窗口仍然关闭。为内容持有者设置填充(始终可点击)或边距(不打任何)。对我来说,它是ListView中的Checkbox。

1 个答案:

答案 0 :(得分:1)

将模板中IsOpen的{​​{1}}属性绑定到控件的Popup属性:

IsChecked

这不会起作用:

<Popup Placement="Bottom"
        x:Name="Popup"
        StaysOpen="False"
        IsOpen="{Binding Path=IsChecked, RelativeSource={RelativeSource AncestorType=local:CustomDropdownButton}, Mode=TwoWay}"
        Child="{TemplateBinding DropdownContent}"/>