簡體   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