在此之前,我为下面详细的问题道歉。由于我是WPF的新手,我决定解释更多,以便获得更多提示!
我有一个UserControl,如:
<UserControl x:Class="MyNamespace.MyUserControl2"...
xmlns:local="clr-namespace:MyNamespace"
Style="{DynamicResource ResourceKey=style1}">
<UserControl.Resources>
<Style x:Key="style1" TargetType="{x:Type UserControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type UserControl}">
...
<local:MyUserControl1 x:Name="myUserControl1" .../>
...
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
</UserControl>
要从后面的代码访问myUserControl1
,我使用了一个属性。
private MyUserControl1 _myUserControl1;
private MyUserControl1 myUserControl1
{
get
{
if (_myUserControl1 == null)
_myUserControl1 = this.Template.FindName("myUserControl1", this) as MyUserControl1;
return _myUserControl1;
}
}
(这是访问模板成员的好方法吗?)
另一方面,MyUserControl2
类(比如DP1
)中有一个依赖属性,负责修改myUserControl1
个依赖属性之一。 (说SomeProperty
)
private static void IsDP1PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var instance = d as MyUserControl2;
if (instance != null)
{
instance.myUserControl1.SomeProperty = function(e.NewValue);
}
}
当我尝试运行上面的代码时,我注意到instance.myUserControl1为null。所以我这样对待它:
if (instance != null && instance.myUserControl1 != null)
{
instance.myUserControl1.SomeProperty = function(e.NewValue);
}
虽然这种方法解决了这个问题,但它会导致myUserControl1.SomeProperty
保持未初始化状态。因此,我将以下代码段放在已加载的事件中以解决它:
private void MyUserControl2_Loaded(object sender, RoutedEventArgs e)
{
this.myUserControl1.SomeProperty = function(DP1);
}
之后,我遇到了另一个问题!
当我使用样式的 setter 属性将某个值设置为DP1
时,我收到了一个 null引用异常,其中显示myUserControl1
属性为已加载事件仍为null。我该如何解决这个问题? -Thanks。
答案 0 :(得分:1)
我猜你还不清楚WPF。
你正在遇到这么多麻烦,因为你的方法很像“类似winforms”,而不是功能性的。如果你坚持以强制性的方式使用它,WPF会让你的生活更加艰难。
首先,模板表示一个函数,用于指示WPF引擎如何在运行时创建实际的可视化树。您应该在托管控件(即MyUserControl2)内的模板 ONLY 中使用该名称作为引用,并从OnApplyTemplate方法中获取实例引用。其他地方。
示例:
private MyUserControl1 _myUserControl1;
public override void OnApplyTemplate()
{
this._myUserControl1 = this.GetTemplateChild("myUserControl1") as MyUserControl1;
//here you should check whether the instance is actually set
}
托管的任何控件的引用应保密为私有:没有任何托管控件的受保护/内部/公开说明。
第二点:如何将两个属性绑定在一起。
您的目标是将控件的属性“绑定”到托管的属性。这项任务绝对正常,它是WPF提供的最佳功能之一。
假设两个属性共享相同的类型,因此可以直接绑定。在您的xaml中:
<ControlTemplate TargetType="{x:Type UserControl}">
...
<local:MyUserControl1 x:Name="myUserControl1"
SomeProperty="{Binding Path=DP1, RelativeSource={RelativeSource Mode=TemplatedParent}}"
.../>
...
</ControlTemplate>
请注意:(1)SomeProperty必须是DependencyProperty,(2)必须是可写的,(3)DP1必须也是DP,或者至少 - 通过INotifyPropertyChanged模式通知任何更改。
描述的语法正常绑定:SomeProperty = DP1,但反之亦然。如果需要双向映射,则应在“绑定”子句中添加“Mode = TwoWay”。
如果要自定义映射这两个属性的函数,只需通过IValueConverter接口定义自己的转换器,然后在xaml中声明它。
您可以在这里找到一些有用的信息:http://msdn.microsoft.com/en-us/library/ms752347.aspx
干杯