You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

在MahApps.MetroWindow中编辑WPF控件模板触发空引用异常的解决方案咨询

在MahApps.MetroWindow中编辑WPF控件模板触发空引用异常的解决方案

我看到你在使用MahApps.MetroWindow时,通过Blend的「编辑模板→编辑副本」功能生成Button模板后,遇到了讨厌的空引用异常,这确实是Blend处理MahApps自定义控件时的常见问题,我来帮你搞定它!

问题根源

Blend在生成模板时,没有正确识别MahApps为控件扩展的附加属性,导致模板里的部分绑定路径不完整,触发了空引用。具体来说是这两处绑定错误:

  • ClipBorderCornerRadius直接写了{TemplateBinding},没有绑定到MahApps的附加属性mah:ControlsHelper.CornerRadius
  • ContentControlExRecognizesAccessKey同样漏写了属性名,直接用{TemplateBinding}导致绑定失效

具体修复步骤

1. 修复CornerRadius绑定

把模板里两个ClipBorderCornerRadius绑定替换为:

CornerRadius="{Binding Path=(mah:ControlsHelper.CornerRadius), RelativeSource={RelativeSource TemplatedParent}}"

因为MahApps是通过ControlsHelper.CornerRadius附加属性来设置Button的圆角,不是Button自身的CornerRadius属性,所以必须指定正确的附加属性路径。

2. 修复RecognizesAccessKey绑定

ContentControlExRecognizesAccessKey属性从{TemplateBinding}改为:

RecognizesAccessKey="{TemplateBinding RecognizesAccessKey}"

这里Blend只是漏写了要绑定的属性名,补上就好。

3. (更省心的方案)基于MahApps默认样式修改

其实你不用重写整个模板,MahApps的控件都有现成的完整样式,直接基于默认样式扩展会更简单,还能避免绑定错误:

<Style x:Key="ButtonStyle1" TargetType="{x:Type Button}" BasedOn="{StaticResource MahApps.Styles.Button}">
    <!-- 只写你需要自定义的Setter,比如修改背景、圆角等 -->
    <Setter Property="Background" Value="{DynamicResource MahApps.Brushes.Gray10}"/>
    <Setter Property="mah:ControlsHelper.CornerRadius" Value="5"/>
</Style>

这种方式会继承所有MahApps的默认绑定、触发器和资源,不用手动维护复杂的模板代码。

修复后的完整ButtonStyle代码

这里给你贴出修正后的完整模板代码,替换你原来的ButtonStyle1即可:

<Style x:Key="ButtonStyle1" TargetType="{x:Type Button}">
    <Setter Property="Background" Value="{DynamicResource MahApps.Brushes.Gray10}"/>
    <Setter Property="BorderBrush" Value="{DynamicResource MahApps.Brushes.Button.Border}"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="FontFamily" Value="{DynamicResource MahApps.Fonts.Family.Button}"/>
    <Setter Property="FontSize" Value="{DynamicResource MahApps.Font.Size.Button}"/>
    <Setter Property="FontWeight" Value="Bold"/>
    <Setter Property="Foreground" Value="{DynamicResource MahApps.Brushes.ThemeForeground}"/>
    <Setter Property="MinHeight" Value="25"/>
    <Setter Property="Padding" Value="5 6"/>
    <Setter Property="SnapsToDevicePixels" Value="True"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid>
                    <mah:ClipBorder x:Name="Border" 
                                    Background="{TemplateBinding Background}" 
                                    BorderBrush="{TemplateBinding BorderBrush}" 
                                    BorderThickness="{TemplateBinding BorderThickness}" 
                                    CornerRadius="{Binding Path=(mah:ControlsHelper.CornerRadius), RelativeSource={RelativeSource TemplatedParent}}" 
                                    SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    <mah:ClipBorder x:Name="DisabledVisualElement" 
                                    Background="{DynamicResource MahApps.Brushes.Control.Disabled}" 
                                    CornerRadius="{Binding Path=(mah:ControlsHelper.CornerRadius), RelativeSource={RelativeSource TemplatedParent}}" 
                                    IsHitTestVisible="False" 
                                    Opacity="0" 
                                    SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    <mah:ContentControlEx x:Name="PART_ContentPresenter" 
                                         ContentCharacterCasing="{Binding (mah:ControlsHelper.ContentCharacterCasing), RelativeSource={RelativeSource Mode=TemplatedParent}}" 
                                         ContentStringFormat="{TemplateBinding ContentStringFormat}" 
                                         ContentTemplate="{TemplateBinding ContentTemplate}" 
                                         Content="{TemplateBinding Content}" 
                                         ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}" 
                                         HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                         Margin="{TemplateBinding BorderThickness}" 
                                         Padding="{TemplateBinding Padding}" 
                                         RecognizesAccessKey="{TemplateBinding RecognizesAccessKey}" 
                                         SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                                         VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" TargetName="Border" Value="{DynamicResource MahApps.Brushes.Gray8}"/>
                        <Setter Property="BorderBrush" TargetName="Border" Value="{Binding (mah:ControlsHelper.MouseOverBorderBrush), Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
                    </Trigger>
                    <Trigger Property="IsPressed" Value="True">
                        <Setter Property="Background" TargetName="Border" Value="{DynamicResource MahApps.Brushes.Gray7}"/>
                    </Trigger>
                    <Trigger Property="IsKeyboardFocusWithin" Value="True">
                        <Setter Property="BorderBrush" TargetName="Border" Value="{Binding (mah:ControlsHelper.FocusBorderBrush), Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
                        <Setter Property="BorderThickness" TargetName="Border" Value="{Binding (mah:ControlsHelper.FocusBorderThickness), Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="Opacity" TargetName="DisabledVisualElement" Value="0.7"/>
                        <Setter Property="Opacity" TargetName="PART_ContentPresenter" Value="0.3"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="mah:ControlsHelper.ContentCharacterCasing" Value="Upper"/>
    <Setter Property="mah:ControlsHelper.CornerRadius" Value="3"/>
    <Setter Property="mah:ControlsHelper.FocusBorderBrush" Value="{DynamicResource MahApps.Brushes.Button.Border.Focus}"/>
    <Setter Property="mah:ControlsHelper.FocusBorderThickness" Value="2"/>
    <Setter Property="mah:ControlsHelper.MouseOverBorderBrush" Value="{DynamicResource MahApps.Brushes.Button.Border.MouseOver}"/>
</Style>

小提示

以后用Blend编辑MahApps控件的模板时,一定要重点检查附加属性的绑定,MahApps大量使用附加属性来扩展控件功能,Blend经常无法自动识别这些属性,容易生成不完整的绑定,这时候手动补全或者直接基于默认样式修改会更高效哦!

火山引擎 最新活动