如何让WPF UserControl在设计时更新?

时间:2017-03-08 08:47:00

标签: c# wpf xaml user-controls design-time

我正在基于UserControl类进行自定义WPF控件。这是一个简单的复选框,矩形有两条对角线,当我缩放整个控件时可以正确缩放。这是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>

我将DependencyProperty IsChecked添加到CustomControl类。如果IsCheckedtrue,则应显示对角线。如果IsCheckedfalse,则应隐藏对角线。它看起来像这样:

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;
                }
            }
        }
    }
 }

当我在我的项目中使用此控件时,我得到了这个XAML:

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

在运行时它运行正常,但在设计时如果我在XAML中更改IsChecked属性,我的CustomCheckbox将不会以图形方式更新。例如,如果我将IsChecked设置为true,则对角线不会显示:

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

这两个控件在设计时在视觉上是相同的。我错过了什么?

1 个答案:

答案 0 :(得分:1)

引用MSDN

  

由于属性设置的XAML处理器行为的当前WPF实现完全绕过包装器,因此不应将任何其他逻辑放入自定义依赖项属性的包装器的集定义中。如果将这样的逻辑放在set定义中,那么当在XAML而不是代码中设置属性时,将不会执行逻辑。

您应该注册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
}

作为旁注,在WPF中,您通常会更换常规CheckBox的模板以更改其外观。