C# 如何使用lambda语句在WPF中初始化UIPropertyMetaData
我知道这很基本,但我不明白。我只想使用lambda操作符将依赖属性C# 如何使用lambda语句在WPF中初始化UIPropertyMetaData,c#,wpf,dependency-properties,C#,Wpf,Dependency Properties,我知道这很基本,但我不明白。我只想使用lambda操作符将依赖属性破折号初始化为双集合 正确的语法是什么 多谢各位 public static readonly DependencyProperty DashesProperty = DependencyProperty.Register("Dashes", typeof(DoubleCollection), typeof(CustomTextBlock), new UIPropertyMetadata(
破折号
初始化为双集合
正确的语法是什么
多谢各位
public static readonly DependencyProperty DashesProperty =
DependencyProperty.Register("Dashes", typeof(DoubleCollection), typeof(CustomTextBlock),
new UIPropertyMetadata(
() =>
{
DoubleCollection d = new DoubleCollection();
d.Add(4);
d.Add(4);
return d;
}
));
不幸的是,这是不可能的。您只能提供值,不能提供值工厂。解决方法是在构造函数中初始化属性:
public CustomTextBlock()
{
Dashes = new DoubleCollection {4, 4};
}
实际上,我刚刚意识到,由于
DoubleCollection
是Freezable
,因此只要调用Freeze
,将DoubleCollection
的实例作为默认值(正如Rohit Vats所建议的那样)就可以工作。你可以这样做:
public static readonly DependencyProperty DashesProperty =
DependencyProperty.Register("Dashes", typeof(DoubleCollection), typeof(CustomTextBlock),
new UIPropertyMetadata(CreateDefaultDashes()));
private static DoubleCollection CreateDefaultDashes()
{
var dashes = new DoubleCollection { 4, 4 };
dashes.Freeze();
return dashes;
}
这使得集合不可变,这意味着它可以在CustomTextBlock
的实例之间安全地共享
好的,实际上默认值似乎是自动冻结的,所以您不需要做任何特殊的事情。它作为默认值是安全的,因为当它被冻结时,它变得不可变。不幸的是,这是不可能的。您只能提供值,不能提供值工厂。解决方法是在构造函数中初始化属性:
public CustomTextBlock()
{
Dashes = new DoubleCollection {4, 4};
}
实际上,我刚刚意识到,由于
DoubleCollection
是Freezable
,因此只要调用Freeze
,将DoubleCollection
的实例作为默认值(正如Rohit Vats所建议的那样)就可以工作。你可以这样做:
public static readonly DependencyProperty DashesProperty =
DependencyProperty.Register("Dashes", typeof(DoubleCollection), typeof(CustomTextBlock),
new UIPropertyMetadata(CreateDefaultDashes()));
private static DoubleCollection CreateDefaultDashes()
{
var dashes = new DoubleCollection { 4, 4 };
dashes.Freeze();
return dashes;
}
这使得集合不可变,这意味着它可以在CustomTextBlock
的实例之间安全地共享
好的,实际上默认值似乎是自动冻结的,所以您不需要做任何特殊的事情。它作为默认值是安全的,因为它在冻结时是不可变的。首先,您应该避免在DP元数据中传递引用类型的默认值,因为这将在您不打算传递的包含类的所有实例中共享
比方说,您声明了CustomTextBlock的两个实例,然后这两个实例都将引用同一个列表,并且列表中的任何修改对这两个实例都是透明的。除非您从构造函数或其他地方显式设置它
不管怎样,如果你还想要它,这里是如何做到的:
new UIPropertyMetadata(new DoubleCollection() { 4, 5 })
更新: 如果在元数据中传递默认值,则DoubleCollection将自动冻结,即在这种情况下,您无法从集合中添加/删除
var dashesCollection = new CustomTextBlock().Dashes.Add(5); // Will throw exception.
但是,如果从构造函数显式设置,则不会将其标记为冻结,并且可以从集合中添加/删除项
var dashesCollection = new CustomTextBlock().Dashes.Add(5); // Works fine.
所以,本质是在构造函数中而不是在DP标识符的元数据中设置值首先,您应该避免在DP元数据中传递引用类型的默认值,因为这将在您不打算传递的包含类的所有实例中共享
比方说,您声明了CustomTextBlock的两个实例,然后这两个实例都将引用同一个列表,并且列表中的任何修改对这两个实例都是透明的。除非您从构造函数或其他地方显式设置它
不管怎样,如果你还想要它,这里是如何做到的:
new UIPropertyMetadata(new DoubleCollection() { 4, 5 })
更新: 如果在元数据中传递默认值,则DoubleCollection将自动冻结,即在这种情况下,您无法从集合中添加/删除
var dashesCollection = new CustomTextBlock().Dashes.Add(5); // Will throw exception.
但是,如果从构造函数显式设置,则不会将其标记为冻结,并且可以从集合中添加/删除项
var dashesCollection = new CustomTextBlock().Dashes.Add(5); // Works fine.
所以,本质是在构造函数中设置值,而不是在DP标识符的元数据中设置值@RohitVats,DoubleCollection是一种类型…@RohitVats,DoubleCollection是一种类型…所以…根本不使用UIPropertyMetadata吗?@AlanWayne,不,在这种情况下您不需要它,因为您无法提供合理的默认值。谢谢。我是新来的。我也想将此标记为一个答案,但我似乎不能标记多个答案。@AlanWayne,不,只能标记一个。。。如果你喜欢这个答案,你可以随时向上投票。所以……根本不使用UIPropertyMetadata?@AlanWayne,不,在这种情况下你不需要它,因为你无法提供合理的默认值。谢谢。我是新来的。我也想将此标记为一个答案,但我似乎不能标记多个答案。@AlanWayne,不,只能标记一个。。。如果您喜欢这个答案,您可以随时向上投票。我认为OP已经意识到引用类型DPs的问题,否则他不会试图使用lambda而不是直接传递值。@RohitVats谢谢。为什么我不打算在所有实例中共享一个常量?@AlanWayne,因为它不是一个真正的常量!DoubleCollection类是可变的:您可以添加、删除或替换其中的项。这些更改将由
CustomTextBlock
的所有实例共享,这可能不是您想要的…@AlanWayne-对于值类型,它确实有意义。但对于引用类型,则不是这样。假设您有两个CustomTextBlock实例,您想在第一个实例的破折号集合中添加5,但在第二个实例中也会添加5,因为它们在内部引用的是同一个集合实例。@Thomas-我刚刚测试了如果在元数据中传递了默认值,默认情况下,它是冻结的,不需要显式调用Freeze()。我认为OP已经意识到引用类型DPs的问题,否则他不会试图使用lambda而不是直接传递值。@RohitVats谢谢。为什么我不打算在所有实例中共享一个常量?@AlanWayne,因为它不是一个真正的常量!DoubleCollection类是可变的:您可以添加、删除或替换其中的项。这些更改将由CustomTextBlock
的所有实例共享,这可能不是您想要的…@AlanWayne-对于值类型,它确实有意义。