You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 8迁移后XAML中自定义控件无法显示的问题

.NET 8迁移后自定义FloatingLabelComboBox控件无法显示问题

问题描述

将项目从.NET 4.8.1迁移至.NET 8后,自定义控件FloatingLabelComboBox无法正常显示,表现为零宽度的空矩形,手动调整宽度后依然为空。该控件样式在Themes.Generic.xaml资源字典中实现,包含依赖属性的C#代码位于FloatingLabelComboBox.CustomControls命名空间下。

相关代码

Generic.xaml代码

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:materialdesign="http://materialdesigninxaml.net/winfx/xaml/themes"
    xmlns:local="clr-namespace:FloatingLabelComboBox">

    <Style TargetType="{x:Type local:CustomControls.FloatingLabelComboBox}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:CustomControls.FloatingLabelComboBox}">
                    <StackPanel FlowDirection="LeftToRight">
                        <Label Content="{TemplateBinding LabelText}"
                               Foreground="{TemplateBinding LabelForeground}"
                               FontSize="{TemplateBinding LabelFontSize}"
                               VerticalAlignment="Stretch"
                               Margin="-5 0 0 0" 
                        />

                        <ComboBox x:Name="comboBox"
                                  ItemsSource="{TemplateBinding ItemsSource}"
                                  SelectedItem="{TemplateBinding SelectedItem}"
                                  SelectedValuePath="{TemplateBinding SelectedValuePath}"
                                  SelectedValue="{TemplateBinding SelectedValue}"
                                  DisplayMemberPath="{TemplateBinding DisplayMemberPath}"
                                  HorizontalAlignment="Stretch"
                                  VerticalAlignment="Center"
                                  Width="Auto"
                                  Height="Auto"
                                  materialdesign:HintAssist.IsFloating="False"
                                  materialdesign:ColorZoneAssist.Mode="Dark"
                                  materialdesign:HintAssist.HintOpacity="0.10"
                                  materialdesign:HintAssist.FontFamily="Century Gothic"
                                  Foreground="{TemplateBinding Foreground}">

                        </ComboBox>
                    </StackPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

C#实现代码

using System.Collections;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace FloatingLabelComboBox.CustomControls
{
    public class FloatingLabelComboBox : Control
    {
        static FloatingLabelComboBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(FloatingLabelComboBox), new FrameworkPropertyMetadata(typeof(FloatingLabelComboBox)));
        }

        public static readonly DependencyProperty LabelTextProperty =
            DependencyProperty.Register("LabelText", typeof(string), typeof(FloatingLabelComboBox), new PropertyMetadata("LabelText"));

        public string LabelText
        {
            get { return (string)GetValue(LabelTextProperty); }
            set { SetValue(LabelTextProperty, value); }
        }

        public static readonly DependencyProperty LabelForegroundProperty =
            DependencyProperty.Register("LabelForeground", typeof(Brush), typeof(FloatingLabelComboBox), new PropertyMetadata(new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFD6931B"))));

        public Brush LabelForeground
        {
            get { return (Brush)GetValue(LabelForegroundProperty); }
            set { SetValue(LabelForegroundProperty, value); }
        }

        public static readonly DependencyProperty LabelFontSizeProperty =
            DependencyProperty.Register("LabelFontSize", typeof(double), typeof(FloatingLabelComboBox), new PropertyMetadata(10.0));

        public double LabelFontSize
        {
            get { return (double)GetValue(LabelFontSizeProperty); }
            set { SetValue(LabelFontSizeProperty, value); }
        }

        public static readonly DependencyProperty ItemsSourceProperty =
            DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(FloatingLabelComboBox), new PropertyMetadata(null));

        public IEnumerable ItemsSource
        {
            get { return (IEnumerable)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }

        public static readonly DependencyProperty SelectedItemProperty =
            DependencyProperty.Register("SelectedItem", typeof(object), typeof(FloatingLabelComboBox), new PropertyMetadata(null));

        public object SelectedItem
        {
            get { return GetValue(SelectedItemProperty); }
            set { SetValue(SelectedItemProperty, value); }
        }

        public static readonly DependencyProperty SelectedValuePathProperty =
            DependencyProperty.Register("SelectedValuePath", typeof(string), typeof(FloatingLabelComboBox), new PropertyMetadata(null));

        public string SelectedValuePath
        {
            get { return (string)GetValue(SelectedValuePathProperty); }
            set { SetValue(SelectedValuePathProperty, value); }
        }

        public static readonly DependencyProperty SelectedValueProperty =
            DependencyProperty.Register("SelectedValue", typeof(object), typeof(FloatingLabelComboBox), new PropertyMetadata(null));

        public object SelectedValue
        {
            get { return GetValue(SelectedValueProperty); }
            set { SetValue(SelectedValueProperty, value); }
        }

        public static readonly DependencyProperty DisplayMemberPathProperty =
            DependencyProperty.Register("DisplayMemberPath", typeof(string), typeof(FloatingLabelComboBox), new PropertyMetadata(null));

        public string DisplayMemberPath
        {
            get { return (string)GetValue(DisplayMemberPathProperty); }
            set { SetValue(DisplayMemberPathProperty, value); }
        }
    }
}

已排查内容

  • XAML文件中自定义控件的命名空间声明正确
  • 自定义控件类的静态构造函数中已重写DefaultStyleKeyProperty
  • AssemblyInfo.cs文件包含必要配置
  • 已重建解决方案
  • XAML文件的生成操作为“Page”,C#文件为“C# compiler”(原.NET 4.8.1中为“Compile”)

解决方案

1. 修正Generic.xaml命名空间引用

当前local命名空间仅声明到FloatingLabelComboBox,但控件实际在子命名空间FloatingLabelComboBox.CustomControls下,需修改命名空间声明:

xmlns:local="clr-namespace:FloatingLabelComboBox.CustomControls"

同时更新Style和ControlTemplate的TargetType:

<Style TargetType="{x:Type local:FloatingLabelComboBox}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:FloatingLabelComboBox}">
                <!-- 原有模板内容不变 -->
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

2. 添加控件默认布局属性

自定义Control默认无明确布局对齐属性,易导致收缩为0,在Style中添加默认值:

<Style TargetType="{x:Type local:FloatingLabelComboBox}">
    <Setter Property="HorizontalAlignment" Value="Stretch"/>
    <Setter Property="VerticalAlignment" Value="Center"/>
    <!-- 原有Template setter -->
</Style>

3. 适配MaterialDesign版本

更新MaterialDesignThemes NuGet包至最新版本,确保与.NET 8兼容,避免样式冲突导致控件不渲染。

4. 优化双向绑定属性

对于SelectedItem、SelectedValue这类需要双向绑定的属性,注册时指定双向绑定默认值:

public static readonly DependencyProperty SelectedItemProperty =
    DependencyProperty.Register("SelectedItem", typeof(object), typeof(FloatingLabelComboBox), 
        new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

同理修改SelectedValue属性的依赖属性注册代码。


内容的提问来源于stack exchange,提问作者Moha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 01:07:47