Tim*_*ler 3 c# wpf xaml user-controls
我正在尝试从XAML设置同一usercontrol的几个实例的fill属性,以便区分它们.我在控件的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>
Run Code Online (Sandbox Code Playgroud)
现在代码隐藏:
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我在主窗口中实例化控件并尝试将填充颜色设置为红色:
<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>
Run Code Online (Sandbox Code Playgroud)
但即使我运行项目,矩形仍未填充.有人可以帮忙吗?
干杯,
蒂姆
我将解释为什么不工作以及如何解决.
1.-只有当usercontrol在可视化树中具有该依赖项属性时,才会调用依赖项属性.
如果你想以这种方式做,你需要添加例如:
new PropertyMetadata(string.Empty, ValueChanged));
Run Code Online (Sandbox Code Playgroud)
并改变了价值:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
这对你的逻辑是明确的,如果你需要一个更通用的代码用于任何颜色等,使用将属性绑定到矩形,请告诉我.
您的依赖项属性有两个问题.
首先,它的类型应该是Brush,而不是字符串,因为这是WPF控件的属性使用的类型,如Shape.Fill或Control.Background.WPF在XAML中提供从"Red"或"#FFFF0000"等字符串到类型Brush的自动类型转换.
其次,除了SetValue在CLR包装器的setter方法中调用之外,你不应该有任何其他东西.原因在MSDN上的XAML加载和依赖属性文章中进行了解释:
由于属性设置的XAML处理器行为的当前WPF实现完全绕过包装器,因此不应将任何其他逻辑放入自定义依赖项属性的包装器的集定义中.如果将这样的逻辑放在set定义中,那么当在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); }
}
Run Code Online (Sandbox Code Playgroud)
要对属性更改做出反应,现在可以使用属性元数据注册PropertyChangedCallback.但是你不需要在这里这样做,因为你可以简单地在UserControl的XAML中绑定属性,如下所示:
<Rectangle Fill="{Binding FillBrush,
RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" ... />
Run Code Online (Sandbox Code Playgroud)