简体   繁体   中英

Why does UserControl textblock vibrates in design mode

When I add my usercontrol to a window, why does the text 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>

Code Behind: 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();
        }
    }

}

Interesting case indeed, and the reason is layout rounding. It seems that wpf designer by default sets UseLayoutRounding to true for the window you view in it. However, in runtime UseLayoutRounding is false for window. What layout rounding means is things like width\\height\\margins are rounded to whole pixel during layout measurment. In your CenterConverter you calculate margin of textblock based on it's own height and width. But changing margin causes width change, and that in turn causes margin change. Because of layout rounding this process never ends.

You can verify that by setting UseLayoutRounding = false explicitly (designer will stop vibrating) or setting to true explicitly (will vibrate in runtime). In general you need to fix CenterConverter to take that into account.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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