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

标签 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"/>

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

最佳答案

引用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. 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.

您应该注册一个 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 的模板来更改其外观。

关于c# - 如何让 WPF UserControl 在设计时更新?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42666702/

相关文章:

c# - 如何在不使用 EF 的情况下连接到 ASP.NET Core Web API 中的数据库?

c# - 通过 Graph API 从 Microsoft Planner 任务中检索附件

wpf - IronPython 或 IronRuby 是否非常适合 WPF/Silverlight 中的 MVVM 模式?

c# WPF AlternateContent 在命名空间中不存在 [...]

c# - 在 Windows 8 商店应用程序上以编程方式将椭圆放置在 Canvas 上

c# - 在 Windows 应用商店应用程序 [XAML/C#] 中淡入/淡出 TextBlock

c# - ASP :Image ImageUrl calling function

c# - 统一.WebApi |确保 Controller 有一个无参数的公共(public)构造函数

wpf - WPF TabControl内存问题

WPF TreeView、 Entity Framework 和带有嵌套子列表的 HierarchicalDataTemplate