简体   繁体   English

如何从XAML设置WPF usercontrol属性?

[英]How to set a WPF usercontrol property from XAML?

I'm trying to set the fill property of several instances of the same usercontrol from XAML in order to distinguish them. 我正在尝试从XAML设置同一usercontrol的几个实例的fill属性,以便区分它们。 I'm using a dependency property in the C# codebehind of the control and referring to that in the XAML when I instantiate the control. 我在控件的C#代码隐藏中使用依赖属性,并在实例化控件时引用XAML中的依赖属性。 Here's a simplified example of what I've tried, first the XAML of the user control: 这是我尝试过的简化示例,首先是用户控件的XAML:

<UserControl x:Class="RectangleFillUserControlTest.RectangleFillTest"
             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" 
             mc:Ignorable="d" 
             d:DesignHeight="50" d:DesignWidth="150">
    <Grid>
        <Rectangle x:Name="rect" HorizontalAlignment="Left" Height="50" Stroke="Black" VerticalAlignment="Top" Width="150"/>
    </Grid>
</UserControl>

Now the codebehind: 现在代码隐藏:

namespace RectangleFillUserControlTest
{
    public partial class RectangleFillTest : UserControl
    {
        SolidColorBrush fillBrush;

        public static readonly DependencyProperty FillColourProperty = DependencyProperty.Register
            ("FillColour", typeof(string), typeof(RectangleFillTest), new PropertyMetadata(string.Empty));

        public string FillColour
        {
            get { return (string)GetValue(FillColourProperty); }

            set
            {
                SetValue(FillColourProperty, value);
                if (value == "red") fillBrush = new SolidColorBrush(Colors.Red);
                else fillBrush = new SolidColorBrush(Colors.Green);
                rect.Fill = fillBrush;
            }
        }

        public RectangleFillTest()
        {
            InitializeComponent();
        }
    }
}

I instantiate the control in the main window and try to set the fill colour to red: 我在主窗口中实例化控件并尝试将填充颜色设置为红色:

<Window x:Class="RectangleFillUserControlTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:RectangleFillUserControlTest"
        Title="MainWindow" Height="350" Width="525">
    <Grid Background="#FF1D2CC3">
        <local:RectangleFillTest FillColour="red"/>
    </Grid>
</Window>

But the rectangle remains unfilled, even when I run the project. 但即使我运行项目,矩形仍未填充。 Can anyone help please? 有人可以帮忙吗?

Cheers, 干杯,

Tim 蒂姆

I will explain why is is not working and how to solve. 我将解释为什么不工作以及如何解决。

1.- A Dependency Property is only called when the usercontrol has that dependency property in the visual tree. 1.-只有当usercontrol在可视化树中具有该依赖项属性时,才会调用依赖项属性。

In case you want to do in that way, you need to add for instance : 如果你想以这种方式做,你需要添加例如:

new PropertyMetadata(string.Empty, ValueChanged));

and there change the value: 并改变了价值:

public static readonly DependencyProperty FillColourProperty = DependencyProperty.Register
        ("FillColour", typeof(string), typeof(RectangleFillTest), new PropertyMetadata(string.Empty, ValueChanged));

    private static void ValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var control = d as RectangleFillTest;
        var fillBrush = new SolidColorBrush();
        if (control.FillColour == "red")
            fillBrush = new SolidColorBrush(Colors.Red);
        else
            fillBrush = new SolidColorBrush(Colors.Green);
        control.rect.Fill = fillBrush;
    }

    public string FillColour
    {
        get
        {
            return (string)GetValue(FillColourProperty);
        }

        set
        {
            SetValue(FillColourProperty, value);

        }
    }

That is explicit for your logic, in case you need a more generic code for any color, etc using binding the property to the rectangle, just tell me. 这对你的逻辑是明确的,如果你需要一个更通用的代码用于任何颜色等,使用将属性绑定到矩形,请告诉我。

There are two things wrong with your dependency property. 您的依赖项属性有两个问题。

First, its type should be Brush , not string, because that is the type used by properties of WPF controls like Shape.Fill or Control.Background . 首先,它的类型应该是Brush ,而不是string,因为它是像Shape.FillControl.Background这样的WPF控件的属性所使用的类型。 WPF provides automatic type conversion from strings like "Red" or "#FFFF0000" in XAML to type Brush. WPF在XAML中提供从“Red”或“#FFFF0000”等字符串到类型Brush的自动类型转换。

Second, you should not have anything else than a call to SetValue in the setter method of the CLR wrapper. 其次,除了在CLR包装器的setter方法中调用SetValue之外,你不应该有任何其他东西。 The reason is explained in the XAML Loading and Dependency Properties article on MSDN: 原因在MSDN上的XAML加载和依赖属性文章中进行了解释:

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. 如果将这样的逻辑放在set定义中,那么当在XAML中而不是在代码中设置属性时,将不会执行逻辑。

So your dependency property declaration should look like this: 所以你的依赖属性声明应如下所示:

public static readonly DependencyProperty FillBrushProperty =
    DependencyProperty.Register(
        "FillBrush", typeof(Brush), typeof(RectangleFillTest));

public Brush FillBrush
{
    get { return (Brush)GetValue(FillBrushProperty); }
    set { SetValue(FillBrushProperty, value); }
}

To react to property changes, you would now register a PropertyChangedCallback with property metadata. 要对属性更改做出反应,现在可以使用属性元数据注册PropertyChangedCallback。 But you don't need to do that here, because you could simply bind the property in the UserControl's XAML like this: 但是你不需要在这里这样做,因为你可以简单地在UserControl的XAML中绑定属性,如下所示:

<Rectangle Fill="{Binding FillBrush,
    RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" ... />

You need to bind your Dependency Property to the Fill property of your Rectangle in the xaml of your UserControl. 您需要将Dependency属性绑定到UserControl的xaml中Rectangle的Fill属性。 You'll have Something like this : 你会有这样的东西:

<Rectangle x:Name="rect" Fill="{Binding FillColour, RelativeSource={RelativeSource FindAncestor, AncestorType=RectangleFillTest}}" HorizontalAlignment="Left" Height="50" Stroke="Black" VerticalAlignment="Top" Width="150"/>

Also, in your dependency property, it's type should be Brush, and not String. 此外,在您的依赖项属性中,它的类型应该是Brush,而不是String。

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

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