如何从 XAML 设置 WPF 用户控件 属性?
How to set a WPF usercontrol property from XAML?
我正在尝试设置来自 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();
}
}
}
我在main中实例化控件window并尝试将填充颜色设置为红色:
<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>
但是矩形仍然没有填充,即使我 运行 项目也是如此。有人可以帮忙吗?
干杯,
蒂姆
您需要将您的依赖项 属性 绑定到您的用户控件 xaml 中矩形的填充 属性。你会得到这样的东西:
<Rectangle x:Name="rect" Fill="{Binding FillColour, RelativeSource={RelativeSource FindAncestor, AncestorType=RectangleFillTest}}" HorizontalAlignment="Left" Height="50" Stroke="Black" VerticalAlignment="Top" Width="150"/>
此外,在您的依赖项 属性 中,它的类型应该是 Brush,而不是 String。
我会解释为什么不起作用以及如何解决。
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);
}
}
这对您的逻辑来说是明确的,如果您需要任何颜色的更通用代码,等等,使用将 属性 绑定到矩形,请告诉我。
您的依赖项有两处错误 属性。
首先,它的类型应该是 Brush
,而不是字符串,因为这是 WPF 控件属性使用的类型,如 Shape.Fill
或 Control.Background
。 WPF 提供从 "Red" 或 XAML 中的“#FFFF0000” 等字符串自动类型转换为类型 Brush.
其次,除了在 CLR 包装器的 setter 方法中调用 SetValue
之外,您不应该有任何其他内容。 MSDN 上的 XAML Loading and Dependency Properties 文章解释了原因:
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.
因此您的依赖项 属性 声明应如下所示:
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}}" ... />
我正在尝试设置来自 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();
}
}
}
我在main中实例化控件window并尝试将填充颜色设置为红色:
<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>
但是矩形仍然没有填充,即使我 运行 项目也是如此。有人可以帮忙吗?
干杯,
蒂姆
您需要将您的依赖项 属性 绑定到您的用户控件 xaml 中矩形的填充 属性。你会得到这样的东西:
<Rectangle x:Name="rect" Fill="{Binding FillColour, RelativeSource={RelativeSource FindAncestor, AncestorType=RectangleFillTest}}" HorizontalAlignment="Left" Height="50" Stroke="Black" VerticalAlignment="Top" Width="150"/>
此外,在您的依赖项 属性 中,它的类型应该是 Brush,而不是 String。
我会解释为什么不起作用以及如何解决。
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);
}
}
这对您的逻辑来说是明确的,如果您需要任何颜色的更通用代码,等等,使用将 属性 绑定到矩形,请告诉我。
您的依赖项有两处错误 属性。
首先,它的类型应该是 Brush
,而不是字符串,因为这是 WPF 控件属性使用的类型,如 Shape.Fill
或 Control.Background
。 WPF 提供从 "Red" 或 XAML 中的“#FFFF0000” 等字符串自动类型转换为类型 Brush.
其次,除了在 CLR 包装器的 setter 方法中调用 SetValue
之外,您不应该有任何其他内容。 MSDN 上的 XAML Loading and Dependency Properties 文章解释了原因:
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.
因此您的依赖项 属性 声明应如下所示:
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}}" ... />