简体   繁体   English

如何在设计时获取WPF UserControl更新?

[英]How to get WPF UserControl to update at design time?

I am making custom WPF control based on UserControl class. 我正在基于UserControl类制作自定义WPF控件。 It's a simple checkbox, rectangle with two diagonal lines that are scaled correctly when I scale whole control. 这是一个简单的复选框,带有两条对角线的矩形,当我缩放整个控件时可以正确缩放。 Here is XAML: 这是XAML:

<UserControl x:Name="Container" 
     x:Class="MyProject.Controls.VirmanCheckbox"
     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:MyProject.Controls"
     mc:Ignorable="d"
     d:DesignHeight="50" d:DesignWidth="50" BorderThickness="1" BorderBrush="Black" Width="50" Height="50" Cursor="Hand" IsTabStop="True" Focusable="True" KeyUp="Grid_KeyUp" GotFocus="Container_GotFocus" LostFocus="Container_LostFocus">
<Grid MouseUp="Grid_MouseUp" Background="#00000000">
    <Line x:Name="diagonal1" X1="0" Y1="0" X2="{Binding Width, ElementName=Container}" Y2="{Binding Height, ElementName=Container}" Stroke="{Binding ElementName=Container, Path=BorderBrush}" StrokeThickness="{Binding ElementName=Container, Path=BorderThickness}" Visibility="Hidden"/>
    <Line x:Name="diagonal2" X1="0" Y1="{Binding Height, ElementName=Container}" X2="{Binding Width, ElementName=Container}" Y2="0" Stroke="{Binding ElementName=Container, Path=BorderBrush}" StrokeThickness="{Binding ElementName=Container, Path=BorderThickness}" Visibility="Hidden"/>
</Grid>

I added DependencyProperty IsChecked to CustomControl class. 我将DependencyProperty IsChecked添加到CustomControl类。 If IsChecked is true diagonal lines should be visible. 如果IsCheckedtrue对角线应可见。 If IsChecked is false diagonal lines should be hidden. 如果IsCheckedfalse对角线应隐藏。 It looks like this: 看起来像这样:

public partial class CustomCheckbox : UserControl
{
    public static readonly DependencyProperty IsCheckedProperty;

    static CustomCheckbox()
    {
        IsCheckedProperty = DependencyProperty.Register(
            name: "IsChecked",
            propertyType: typeof(Boolean),
            ownerType: typeof(VirmanCheckbox),
            typeMetadata: new FrameworkPropertyMetadata(
                defaultValue: false, 
                flags: FrameworkPropertyMetadataOptions.AffectsRender
            )
        );
    }

    public bool IsChecked
    {
        get { return (bool)GetValue(IsCheckedProperty); }
        set
        {
            var old = (bool)GetValue(IsCheckedProperty);
            SetValue(IsCheckedProperty, value);

            if (old != value)
            {
                if (value)
                {
                    diagonal1.Visibility = Visibility.Visible;
                    diagonal2.Visibility = Visibility.Visible;
                }
                else
                {
                    diagonal1.Visibility = Visibility.Hidden;
                    diagonal2.Visibility = Visibility.Hidden;
                }
            }
        }
    }
 }

When I use this control in my project I get this XAML: 当我在项目中使用此控件时,将得到以下XAML:

<Controls:CustomCheckbox HorizontalAlignment="Left" VerticalAlignment="Top"/>

During runtime it works perfectly, but during design time if I change IsChecked property in XAML my CustomCheckbox won't graphically update. 在运行时,它可以完美运行,但是在设计时,如果我更改XAML中的IsChecked属性,则CustomCheckbox不会以图形方式更新。 For example, if I set IsChecked to true , diagonal lines won't show: 例如,如果我将IsChecked设置为true ,对角线将不会显示:

<Controls:CustomCheckbox HorizontalAlignment="Left" VerticalAlignment="Top" IsChecked="True"/>
<Controls:CustomCheckbox HorizontalAlignment="Left" VerticalAlignment="Top" IsChecked="False"/>

These two controls are visually same during design time. 在设计时,这两个控件在外观上是相同的。 What am I missing? 我想念什么?

Quoting MSDN : 引用MSDN

Because the current WPF implementation of the XAML processor behavior for property setting bypasses the wrappers entirely, you should not put any additional logic into the set definitions of the wrapper for your custom dependency property. 由于XAML处理器当前针对属性设置的行为的WPF实现完全绕过了包装器,因此您不应为自定义依赖项属性在包装器的集合定义中添加任何其他逻辑。 If you put such logic in the set definition, then the logic will not be executed when the property is set in XAML rather than in code. 如果将这样的逻辑放在集合定义中,则当在XAML中而不是在代码中设置属性时,将不会执行该逻辑。

You should register a PropertyChangedCallback instead. 您应该改为注册PropertyChangedCallback

public partial class CustomCheckbox : UserControl
{
    public CustomCheckbox()
    {
        InitializeComponent();
    }

    #region IsChecked
    public static readonly DependencyProperty IsCheckedProperty =
        DependencyProperty.Register("IsChecked",
            typeof(bool), typeof(CustomCheckbox),
            new FrameworkPropertyMetadata(
                false, 
                FrameworkPropertyMetadataOptions.AffectsRender,
                IsCheckedPropertyChanged));

    public bool IsChecked
    {
        get { return (bool)GetValue(IsCheckedProperty); }
        set { SetValue(IsCheckedProperty, value); }
    }
    #endregion

    #region IsCheckedPropertyChanged
    private static void IsCheckedPropertyChanged
        (DependencyObject source, DependencyPropertyChangedEventArgs e)
    {
        if (source is CustomCheckbox)
        {
            CustomCheckbox control = source as CustomCheckbox;
            bool value = (bool)e.NewValue;

            if (value)
            {
                control.diagonal1.Visibility = Visibility.Visible;
                control.diagonal2.Visibility = Visibility.Visible;
            }
            else
            {
                control.diagonal1.Visibility = Visibility.Hidden;
                control.diagonal2.Visibility = Visibility.Hidden;
            }
        }
    }
    #endregion
}

As a side note, in WPF you would usually swap the template of a regular CheckBox to change it's appearance. 附带说明一下,在WPF中,您通常会交换常规CheckBox的模板以更改其外观。

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

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