如何在自定义 WPF 控件中允许 Width=“Auto”
本文关键字:Width Auto 自定义 WPF 控件 | 更新日期: 2023-09-27 18:30:50
我创建了一个基于 Expander 类的自定义控件:
public partial class HideableExpander : Expander
{
public new double Height
{
get
{
if (Visibility== System.Windows.Visibility.Hidden)
{
return 0;
}
return base.Height;
}
set
{
base.Height = value;
}
}
public new double Width
{
get
{
if (Visibility == System.Windows.Visibility.Hidden)
{
return 0;
}
return base.Width;
}
set
{
base.Width = value;
}
}
public new Thickness Margin
{
get
{
if (Visibility== System.Windows.Visibility.Hidden)
{
return new Thickness();
}
return base.Margin;
}
set
{
base.Margin = value;
}
}
public HideableExpander()
{
this.InitializeComponent();
}
}
XAML:
<Expander
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="leartWPF.HideableExpander"
x:Name="UserControl"
d:DesignWidth="640" d:DesignHeight="480">
<Grid x:Name="LayoutRoot"/>
</Expander>
现在,当我尝试将其与 Width="Auto" 属性一起使用时:
<local:HideableExpander Header="{Binding Expander1Name, ElementName=Window}" Margin="10" Width="Auto" Background="#00F19494" VerticalAlignment="Top" >
<WrapPanel Height="Auto" Margin="0" Width="Auto" >
<TextBlock Text="Please, enter the name of this expander: " VerticalAlignment="Center"/>
<TextBox Width="150" Text="{Binding Expander1Name, ElementName=Window, Mode=TwoWay, NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" Background="#FFF5EECC"/>
</WrapPanel>
</local:HideableExpander>
我收到一个关于无法将"自动"转换为双精度的异常:
Unhandled Exception: System.Windows.Markup.XamlParseException: 'Provide value on 'System.Windows.Baml2006.TypeConverterMarkupExtension' threw an exception.' Line number '10' and line position '8'. ---> System.Exception: Auto is not a valid value for Double. ---> System.FormatException: Input string was not in a correct format.
at System.Number.ParseDouble(String value, NumberStyles options, NumberFormatInfo numfmt)
at System.Double.Parse(String s, NumberStyles style, IFormatProvider provider)
at System.ComponentModel.DoubleConverter.FromString(String value, NumberFormatInfo formatInfo)
at System.ComponentModel.BaseNumberConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
--- End of inner exception stack trace ---
at System.ComponentModel.BaseNumberConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
at MS.Internal.Xaml.Runtime.ClrObjectRuntime.CallProvideValue(MarkupExtension me, IServiceProvider serviceProvider)
--- End of inner exception stack trace ---
at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri)
at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)
at System.Windows.Application.LoadBamlStreamWithSyncInfo(Stream stream, ParserContext pc)
at System.Windows.Application.LoadComponent(Uri resourceLocator, Boolean bSkipJournaledProperties)
at System.Windows.Application.DoStartup()
at System.Windows.Application.<.ctor>b__1(Object unused)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.DispatcherOperation.InvokeImpl()
at System.Threading.ExecutionContext.runTryCode(Object userData)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Windows.Threading.DispatcherOperation.Invoke()
at System.Windows.Threading.Dispatcher.ProcessQueue()
at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
at System.Windows.Application.RunInternal(Window window)
at System.Windows.Application.Run()
at leartWPF.App.Main() in d:'Users'menkaur'Documents'Expression'Blend 4'Projects'leartWPF'leartWPF'obj'Debug'App.g.cs:line 0
我应该怎么做才能接受自动作为值?
您需要在属性上使用 TypeConverter
属性,应使用指定LengthConverter
。 然后将Auto
转换为 Double.NaN
。
(您可以在FrameworkElement
属性Width
和Height
上看到此操作)
尝试添加以下属性,我认为这应该会有所帮助,当然,"新"可以隐藏父级的宽度...
[TypeConverterAttribute(typeof(LengthConverter))]
public new double Width
{
......your getter and setter
编辑 每条评论: -"什么是 getter 和 setter?
//getter and setter sample(grabbing them from the question)
get
{
if (Visibility == System.Windows.Visibility.Hidden)
{
return 0;
}
return base.Width;
}
set
{
base.Width = value;
}
}