【问题标题】:How to set a WPF usercontrol property from XAML?如何从 XAML 设置 WPF 用户控件属性?
【发布时间】:2015-05-13 21:41:47
【问题描述】:

我正在尝试从 XAML 中设置同一用户控件的多个实例的填充属性,以便区分它们。我在控件的 C# 代码隐藏中使用依赖属性,并在实例化控件时在 XAML 中引用该属性。这是我尝试过的一个简化示例,首先是用户控件的 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>

现在是代码隐藏:

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

我在主窗口中实例化控件并尝试将填充颜色设置为红色:

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

但即使我运行项目,矩形仍然没有填充。有人可以帮忙吗?

干杯,

提姆

【问题讨论】:

    标签: c# wpf xaml user-controls


    【解决方案1】:

    你的依赖属性有两个问题。

    首先,它的类型应该是Brush,而不是字符串,因为这是诸如Shape.FillControl.Background 等WPF 控件的属性所使用的类型。 WPF 提供从 XAML 中的“Red”或“#FFFF0000”等字符串到类型 Brush 的自动类型转换。

    其次,除了在 CLR 包装器的 setter 方法中调用 SetValue 之外,您不应该有其他任何东西。原因在 MSDN 上的XAML Loading and Dependency Properties 文章中有说明:

    因为 XAML 处理器行为的当前 WPF 实现 对于属性设置完全绕过包装,你不应该 将任何附加逻辑放入包装器的集合定义中 您的自定义依赖项属性。如果你把这样的逻辑放在集合中 定义,那么当属性为 在 XAML 中而不是在代码中设置。

    所以你的依赖属性声明应该是这样的:

    public static readonly DependencyProperty FillBrushProperty =
        DependencyProperty.Register(
            "FillBrush", typeof(Brush), typeof(RectangleFillTest));
    
    public Brush FillBrush
    {
        get { return (Brush)GetValue(FillBrushProperty); }
        set { SetValue(FillBrushProperty, value); }
    }
    

    要对属性更改做出反应,您现在需要使用属性元数据注册一个 PropertyChangedCallback。但是您不需要在这里这样做,因为您可以像这样简单地绑定 UserControl 的 XAML 中的属性:

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

    【讨论】:

    • 感谢您的质量解释、优秀的代码以及绑定信息。提示更多关于如何将哪个绑定到什么的迫切问题,即将推出。
    • 你好克莱门斯,我尝试了两种解决方案,都完全解决了我的问题。我不确定在这种情况下接受哪个答案的礼仪,所以我接受了 Juan 的答案,他会从额外的代表中受益更多。希望这没问题。再次感谢您的时间和精力。
    • 您应该接受对您最有帮助并且您认为最好的答案。仅仅因为您认为作者可以从声誉积分中受益而接受答案是错误的,并且可能会误导他人。
    • 好的,我接受了 Juan 的回答,因为这并不意味着深入研究绑定。你的可能是更好的答案,但我真的没有资格判断,除了我是英国人,所以不喜欢说我更喜欢一个而不是另一个来让人们不高兴。希望这可以消除任何困惑,也希望在不久的将来再次从您的帮助中受益。干杯...
    【解决方案2】:

    我会解释为什么不工作以及如何解决。

    1.- 只有当用户控件在可视化树中具有该依赖属性时,才会调用依赖属性。

    如果你想这样做,你需要添加例如:

    new PropertyMetadata(string.Empty, ValueChanged));
    

    然后改变值:

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

    这对您的逻辑很明确,如果您需要使用将属性绑定到矩形的任何颜色等更通用的代码,请告诉我。

    【讨论】:

    • 在搜索了几个小时之后,这终于成功了。非常感谢您指出 ValueChanged 回调!
    【解决方案3】:

    您需要在 UserControl 的 xaml 中将 Dependency 属性绑定到 Rectangle 的 Fill 属性。你会有这样的东西:

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

    另外,在你的依赖属性中,它的类型应该是 Brush,而不是 String。

    【讨论】:

      猜你喜欢
      • 2011-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-12
      相关资源
      最近更新 更多