繁体   English   中英

为什么 UserControl 文本块在设计模式下会振动

[英]Why does UserControl textblock vibrates in design mode

当我将用户控件添加到窗口时,为什么文本在设计模式下振动?。
问题视频

<UserControl x:Class="AircraftGauges.InnerGauge"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:AircraftGauges"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="200"
             DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <UserControl.Resources>
        <local:CenterConverter x:Key="CenterConverter"/>
    </UserControl.Resources>
    <Canvas Width="200" Height="200" Background="White">
        <Path Stroke="Black" StrokeThickness="1" Data="M 40, 95 V 105 H 160 V 95 H 105 V 85 H 95 V 95 Z " Fill="Black"/>
        <TextBlock Name="CenterLabel" Text="{Binding PathData}" Foreground="Black" VerticalAlignment="Center"
                       Canvas.Left="100" Canvas.Top="112">
            <TextBlock.Margin>
                <MultiBinding Converter="{StaticResource CenterConverter}">
                    <Binding ElementName="CenterLabel" Path="ActualWidth"/>
                    <Binding ElementName="CenterLabel" Path="ActualHeight"/>
                </MultiBinding>
            </TextBlock.Margin>
        </TextBlock>
    </Canvas>
</UserControl>

隐藏代码:InnerGauge.xaml.cs:

namespace AircraftGauges
{
    /// <summary>
    /// Interaction logic for InnerGauge.xaml
    /// </summary>
    public partial class InnerGauge : UserControl, INotifyPropertyChanged
    {
        private string _path;

        public event PropertyChangedEventHandler PropertyChanged;

        public InnerGauge()
        {
            InitializeComponent();

            SizeChanged += SizeChangedEventHandler;
        }

        private void SizeChangedEventHandler(object sender, SizeChangedEventArgs e)
        {
            UpdatePathData(e.NewSize.Width, e.NewSize.Height);
        }

        private void UpdatePathData(double w, double h)
        {
            var newPath = $"W {w} -- H {h}";

            if (String.CompareOrdinal(_path, newPath) != 0)
            {
                _path = newPath;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(PathData)));
            }
        }

        public string PathData
        {
            get
            {
                return _path;
            }
        }
    }
}

CenterConverter.cs

namespace AircraftGauges
{
    public class CenterConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (values[0] == DependencyProperty.UnsetValue || values[1] == DependencyProperty.UnsetValue)
            {
                return DependencyProperty.UnsetValue;
            }

            var width = (double) values[0];
            var height = (double) values[1];

            return new Thickness(-width/2, -height/2, 0, 0);
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

}

确实很有趣,原因是布局四舍五入。 对于您在其中查看的窗口,wpf 设计器似乎默认将 UseLayoutRounding 设置为 true 。 但是,在运行时 UseLayoutRounding 对于窗口是假的。 布局四舍五入的意思是在布局测量期间将宽度\\高度\\边距四舍五入到整个像素。 在您的 CenterConverter 中,您根据它自己的高度和宽度计算文本块的边距。 但是改变边距会导致宽度改变,进而导致边距改变。 由于布局四舍五入,这个过程永远不会结束。

您可以通过显式设置 UseLayoutRounding = false (设计器将停止振动)或显式设置为 true (将在运行时振动)来验证这一点。 通常,您需要修复 CenterConverter 以将其考虑在内。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM