c# – 将自定义依赖项属性添加到XAML中的控制模板

经过一段时间的休息后,我已经设法进一步使用了我的只读复选框,现在我以理想的优雅形式拥有了我想要的功能.问题是我已经使用了一些黑客来使它工作,虽然这不是一个灾难,它会更好地做到这一点.

回顾一下:我想要一个常规查看的复选框,在单击它时不会自我检查,而是单击事件会触发后台工作程序,稍后会导致更新变量.此变量绑定到checkbox.ischecked,然后使用新值更新.

我想在这里使用基于这个想法的控件模板:

A read-only CheckBox in C# WPF

我修改了这个并剥离了我认为我不需要的东西(也许是不明智的)并最终得到:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero">
<!-- -->
<Style x:Key="ReadOnlyCheckBoxStyle" TargetType="{x:Type CheckBox}" >
        <Setter Property="Control.Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type CheckBox}">
                <BulletDecorator SnapsToDevicePixels="true" Background="Transparent">
                    <BulletDecorator.Bullet>
                        <Microsoft_Windows_Themes:BulletChrome Background="{TemplateBinding Background}"
                                                               BorderBrush="{TemplateBinding BorderBrush}"
                                                               RenderMouseOver="{TemplateBinding IsMouseOver}"
                                                               IsChecked="{TemplateBinding Tag}">
                        </Microsoft_Windows_Themes:BulletChrome>
                    </BulletDecorator.Bullet>
                    <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                      HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                      Margin="{TemplateBinding Padding}"
                                      VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                      RecognizesAccessKey="True" />
                </BulletDecorator>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Foreground" Value="{StaticResource {x:Static SystemColors.GrayTextBrushKey}}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

这个复选框的工作方式如上所述,我这样称呼它:

<CheckBox x:Name="uiComboBox" Content="Does not set the backing property, but responds to it." 
                  Style="{StaticResource ReadOnlyCheckBoxStyle}" Tag="{Binding MyBoolean}" Click="uiComboBox_Click"/>

我做的黑客是使用’Tag’DependencyProperty将数据绑定带到控件模板中.这绕过了通常导致复选框自检的任何机制.要恢复到正常操作复选框,只需将绑定更改为Tag以绑定到IsChecked,并在BulletDecorator内部将TemplateBinding设置为IsChecked而不是Tag.

所以我想我的问题是:

>我有错误的结束吗?有没有一个地方我可以覆盖任何机制导致盒子自我检查?也许在ControlTemplate Triggers中?
>绕过消除我认为刚刚从默认CheckBox引入的任何备用XAML或者我是否应该尝试保留所有样式的完全替代品,这是一个好主意吗?
>如果我正在做的事情不是太疯狂,我可以在XAML中添加依赖项属性,这样我就不必使用Tag属性了吗?
>我也想到,也许我真正想要的是一个看起来像一个复选框的按钮控件,可能是一个隐形按钮,顶部有通常的动画复选框,我将数据绑定到图形.对该计划的任何想法也将非常受欢迎.

非常感谢

埃德

解决方法:

我设法解决了这个问题和我的ReadOnlyCheckBox想法,最后我创建了一个基于Button的自定义控件,然后应用了一个样式使它看起来像CheckBox.我添加了自己的IsChecked属性,该属性在用户单击时未设置但已绑定到数据,因此显示的检查仅在数据更改时显示.

C#:

    public class ReadOnlyCheckBoxControl : System.Windows.Controls.Button
{
    public static DependencyProperty IsCheckedProperty;

    public ReadOnlyCheckBoxControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(ReadOnlyCheckBoxControl), new FrameworkPropertyMetadata(typeof(ReadOnlyCheckBoxControl)));
    }

    public bool IsChecked
    {
        get { return (bool)GetValue(IsCheckedProperty); }
        set { SetValue(IsCheckedProperty, value); }
    }

    static ReadOnlyCheckBoxControl()
    {
        IsCheckedProperty = DependencyProperty.Register("IsChecked", typeof(bool), typeof(ReadOnlyCheckBoxControl));
    }
}

XAML:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:y="clr-namespace:ReadOnlyCheckBoxControlNS;assembly="
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero">

<SolidColorBrush x:Key="CheckBoxFillNormal" Color="#F4F4F4" />
<SolidColorBrush x:Key="CheckBoxStroke" Color="#8E8F8F" />

<Style x:Key="EmptyCheckBoxFocusVisual">
    <Setter Property="Control.Template">
        <Setter.Value>
            <ControlTemplate>
                <Rectangle SnapsToDevicePixels="true"
                           Margin="1"
                           Stroke="Black"
                           StrokeDashArray="1 2"
                           StrokeThickness="1" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style x:Key="CheckRadioFocusVisual">
    <Setter Property="Control.Template">
        <Setter.Value>
            <ControlTemplate>
                <Rectangle SnapsToDevicePixels="true"
                           Margin="14,0,0,0"
                           Stroke="Black"
                           StrokeDashArray="1 2"
                           StrokeThickness="1" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style TargetType="{x:Type y:ReadOnlyCheckBoxControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type y:ReadOnlyCheckBoxControl}">
                <BulletDecorator SnapsToDevicePixels="true" Background="Transparent">
                    <BulletDecorator.Bullet>
                        <Microsoft_Windows_Themes:BulletChrome Background="{StaticResource CheckBoxFillNormal}"
                                                               BorderBrush="{StaticResource CheckBoxStroke}"
                                                               RenderMouseOver="{TemplateBinding IsMouseOver}"
                                                               IsChecked="{TemplateBinding IsChecked}">
                        </Microsoft_Windows_Themes:BulletChrome>
                    </BulletDecorator.Bullet>
                    <ContentPresenter SnapsToDevicePixels="True"
                                      HorizontalAlignment="Left"
                                      Margin="4,0,0,0"
                                      VerticalAlignment="Center"
                                      RecognizesAccessKey="True" />
                </BulletDecorator>
                <ControlTemplate.Triggers>
                    <Trigger Property="HasContent" Value="true">
                        <Setter Property="FocusVisualStyle" Value="{StaticResource CheckRadioFocusVisual}" />
                        <Setter Property="Padding" Value="4,0,0,0" />
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Foreground" Value="{StaticResource {x:Static SystemColors.GrayTextBrushKey}}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
上一篇:c# – 如何将WPF效果颜色绑定到ControlTemplate的前景或背景


下一篇:【转】WPF Template模版之DataTemplate与ControlTemplate的关系和应用(二)