.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
相关产品推荐
相关产品推荐

