C# 向XAML中的控件模板添加自定义依赖项属性

C# 向XAML中的控件模板添加自定义依赖项属性,c#,xaml,binding,checkbox,controltemplate,C#,Xaml,Binding,Checkbox,Controltemplate,在稍作休息之后,我成功地进一步使用了只读复选框,现在以一种相当优雅的形式拥有了我想要的功能。问题是我用了一点技巧让它工作起来,虽然这不是一场灾难,但最好能做得更好 总而言之:我想要一个常规的复选框,当它被点击时不会进行自检,相反,点击事件会触发一个后台工作程序,稍后会导致一个变量被更新。此变量绑定到checkbox.ischecked,然后用新值更新 我想使用基于以下想法的控件模板: 我修改了这个,去掉了我认为不需要的东西(可能是不明智的),最后得到了: <ResourceDiction

在稍作休息之后,我成功地进一步使用了只读复选框,现在以一种相当优雅的形式拥有了我想要的功能。问题是我用了一点技巧让它工作起来,虽然这不是一场灾难,但最好能做得更好

总而言之:我想要一个常规的复选框,当它被点击时不会进行自检,相反,点击事件会触发一个后台工作程序,稍后会导致一个变量被更新。此变量绑定到checkbox.ischecked,然后用新值更新

我想使用基于以下想法的控件模板:

我修改了这个,去掉了我认为不需要的东西(可能是不明智的),最后得到了:

<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”dependencProperty将数据绑定携带到控件模板中。这绕过了通常导致复选框自检的任何机制。要恢复到正常作用复选框,只需将binding To Tag更改为binding To IsChecked,并在BulletDecorator内将TemplateBinding设置为IsChecked而不是Tag

所以我想我的问题是:

  • 我是不是找错了方向了?有没有一个地方可以让我覆盖任何导致盒子自检的机制?也许在ControlTemplate触发器中
  • 消除我认为只是从默认复选框中引入的任何备用XAML是一个好主意,还是应该尝试为所有样式保留一个完整的替代品
  • 如果我所做的不是太疯狂,我可以在XAML中添加一个dependency属性,这样我就不必使用Tag属性了吗
  • 我还想到,也许我真正想要的是一个看起来像复选框的按钮控件,也许是一个不可见的按钮,上面有一个通常的动画复选框,我将数据绑定到该控件的图形。对该计划的任何想法都将是非常受欢迎的
  • 非常感谢


    Ed

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

    C#:

    XAML:

    
    

        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));
        }
    }
    
    <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>