依赖属性聚集在单独的类中
我的问题涉及 Silverlight(但我猜 WPF 也是如此)。
基本上我知道如何在用户控件中创建依赖属性以及如何使其工作。但我试图做但没有成功的是:在类中创建依赖属性(或多个),并且该类将成为我的用户控件的依赖属性。
换句话说:
// my UserControl
public class DPTest : UserControl
{
// dependency property, which type is a class, and this class will be holding other dependency properties
public static readonly DependencyProperty GroupProperty =
DependencyProperty.Register("Group", typeof(DPGroup), typeof(DPTest), new PropertyMetadata(new DPGroup(), OnPropertyChanged));
public DPGroup Group
{
get { return (DPGroup)GetValue(GroupProperty); }
set { SetValue(GroupProperty, value); }
}
// this occurs only when property Group will change, but not when a member of property Group will change
static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
DPTest g = d as DPTest;
// etc.
}
}
// a class, where I want to hold my dependency properties
public class DPGroup : DependencyObject
{
public static readonly DependencyProperty MyProperty1Property =
DependencyProperty.RegisterAttached("MyProperty1", typeof(int), typeof(DPGroup), new PropertyMetadata(1, OnPropertyChanged));
public int MyProperty1
{
get { return (int)GetValue(MyProperty1Property); }
set { SetValue(MyProperty1Property, value); }
}
// I would like to notify "the parent" (which means user control "DPTest" ), that member MyProperty1 has changed
static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
DPTest g = d as DPTest;
if (g != null) g.textBox1.Text = g.Group.MyProperty1.ToString();
}
}
我想要实现的是通知(在XAML中的设计时)用户控件DPTest
,即Group
属性的成员(Group.MyProperty1
)更改了它的值。我设法使其在运行时发生,例如通过使用 DPGroup 类中定义的事件处理程序,但这在 xaml 的设计时不起作用。
<Grid x:Name="LayoutRoot" Background="White">
<local:DPTest>
<local:DPTest.Group>
<local:DPGroup MyProperty1="2"/>
</local:DPTest.Group>
</local:DPTest>
</Grid>
它可以工作,但只是第一次,在创建标记期间:
<local:DPGroup MyProperty1="2"/>
此后,更改 MyProperty1
的值,不会触发 DPTest.OnPropertyChange
。可能会触发DBGroup.OnPropertyChanged
,但这当然不会通知用户控件DPTest
。 那么如何让 DPTest
知道 Group.MyProperty1
已更改?
我不想从 MyProperty1 进行任何绑定
到用户控件 DPTest
内创建的各个属性(不要重复属性),重点是在单独的类中拥有一组属性,因此我可以多次使用该组,例如:
// my UserControl
public class DPTest : UserControl
{
public DPGroup Group1 { ... }
public DPGroup Group2 { ... }
}
我看到一些类比UIElement.RenderTransform
(假设它是我的 Group
属性),例如 ScaleTransform
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RenderTransform>
<ScaleTransform ScaleX="0.4"/>
</Grid.RenderTransform>
</Grid>
ScaleX
是一个类比MyProperty1
。 不同之处在于,改变 ScaleX
的值(在 XAML 中)将反映设计时的立即变化,而这正是我想要实现的。
我试图找到整个谷歌/堆栈溢出和其他问题的解决方案,但没有找到。到处都是在用户控件内创建依赖属性的示例。
感谢您抽出时间。 非常感谢任何帮助。
编辑:根据 Harlow Burgess 的回答,成功地在 Silverlight 中制作了一个工作示例。我将整个解决方案作为单独的答案放在下面。
My question concerns Silverlight (but I guess WPF as well).
Basically I know, how to create dependency property in a user control and how to make it work. But what i was trying to do, and didn't succeded is: to create dependency property (or more than one) in a class, and this class will become a dependency property for my user control.
With other words:
// my UserControl
public class DPTest : UserControl
{
// dependency property, which type is a class, and this class will be holding other dependency properties
public static readonly DependencyProperty GroupProperty =
DependencyProperty.Register("Group", typeof(DPGroup), typeof(DPTest), new PropertyMetadata(new DPGroup(), OnPropertyChanged));
public DPGroup Group
{
get { return (DPGroup)GetValue(GroupProperty); }
set { SetValue(GroupProperty, value); }
}
// this occurs only when property Group will change, but not when a member of property Group will change
static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
DPTest g = d as DPTest;
// etc.
}
}
// a class, where I want to hold my dependency properties
public class DPGroup : DependencyObject
{
public static readonly DependencyProperty MyProperty1Property =
DependencyProperty.RegisterAttached("MyProperty1", typeof(int), typeof(DPGroup), new PropertyMetadata(1, OnPropertyChanged));
public int MyProperty1
{
get { return (int)GetValue(MyProperty1Property); }
set { SetValue(MyProperty1Property, value); }
}
// I would like to notify "the parent" (which means user control "DPTest" ), that member MyProperty1 has changed
static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
DPTest g = d as DPTest;
if (g != null) g.textBox1.Text = g.Group.MyProperty1.ToString();
}
}
What I want to achieve is to notify (in design time in XAML) a user control DPTest
, that member of Group
property (Group.MyProperty1
) changed it's value. I managed to make it happen in a run-time, for example by using event handler defined in DPGroup
class, but this doesn't work in design-time in xaml.
<Grid x:Name="LayoutRoot" Background="White">
<local:DPTest>
<local:DPTest.Group>
<local:DPGroup MyProperty1="2"/>
</local:DPTest.Group>
</local:DPTest>
</Grid>
It works, but only first time, during creating tag:
<local:DPGroup MyProperty1="2"/>
and after this, changing value of MyProperty1
, does not fire DPTest.OnPropertyChange
. Probably fires DBGroup.OnPropertyChanged
, but this of course does not notify user control DPTest
about it. So how to make DPTest
know, that the Group.MyProperty1
has changed?
I don't want to make any bindings from MyProperty1
to respective property created inside user control DPTest
(not to duplicate properties), the point is to have a group of properties in separate class, so i can use this group more than once, like:
// my UserControl
public class DPTest : UserControl
{
public DPGroup Group1 { ... }
public DPGroup Group2 { ... }
}
I see some analogy to UIElement.RenderTransform
(let's say it is my Group
property) which holds for example ScaleTransform
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RenderTransform>
<ScaleTransform ScaleX="0.4"/>
</Grid.RenderTransform>
</Grid>
ScaleX
is an analogy to MyProperty1
. The difference is, that changing value of ScaleX
(in XAML) will reflect immediate changes in design-time, and exactly this I am trying to achieve.
I was trying to find a solution in entire google/stack overflow and others, but none found. Everywhere are just examples of creating dependency properties inside a user control.
Thank you for your time.
Any help much appreciated.
edit: based on Harlow Burgess answer, a managed to make a working example in Silverlight. I put the whole solution below as an separate answer.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
来自: http://msdn.microsoft.com/en-us/library /ms752914.aspx#setting_properties_data_binding
设计一个在任何子属性(任何子属性、任何子属性……)的任何属性发生变化时通知整个对象图的系统是低效的。因此,当您需要在属性更改时执行某些操作时,或者如果您确实希望在任何子属性更改时收到通知,则应该使用数据绑定到特定属性,您应该实现INotifyPropertyChanged。
如何:实现属性更改通知
示例:
From: http://msdn.microsoft.com/en-us/library/ms752914.aspx#setting_properties_data_binding
It would be inefficient to design a system that notifies an entire object graph anytime any property of any subproperty (of any subproperty, of any subproperty, ...) changes. So instead you should use Data Binding to specific properties when you need to do something when that property changes, or if you really want to be notified when any subproperty changes, you should implement INotifyPropertyChanged.
How to: Implement Property Change Notification
Example:
好的,根据 @Harlow Burgess 的回答,我成功地在 Silverlight 中制作了一个工作示例。
基本上区别在于,在 SL 中,
DependencyObject
类没有OnPropertyChanged
方法,因此在DPGroup
类中我们无法重写它,但我们可以附加它此方法以另一种方式,通过:因此
DPGroup
类将如下所示:父类,包含类型
DPGroup
的依赖属性:现在,
DPGroup
类的 XAML 部分代码>DPTest:最后,我们可以将
DPTest
嵌入到任何控件的某些内容中,例如嵌入到另一个用户控件的Grid
中:仅此而已,再次感谢 Harlow Burgess 的帮助!
Ok, so based on @Harlow Burgess answer, a managed to make a working example in Silverlight.
Basically the difference is, that in SL,
DependencyObject
class has noOnPropertyChanged
method, so inDPGroup
class we cannot override it, but we can attach this method in another way, by:So the
DPGroup
class will look like this:And the parent class, containing dependency property of type
DPGroup
:Now, the XAML part for
DPTest
:Finally, we can embed our
DPTest
in some content of any control, for example in aGrid
of another user control:That is all, thanks again to the Harlow Burgess for the help!