2011-09-18 128 views
0

在此之前,我對以下詳細問題表示歉意。由於我是WPF的新手,我決定解釋更多,以便獲得更多提示!如何使用模板成員屬性


我有一個用戶控件,如:

<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爲空。所以,我對待它像這樣:

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); 
} 

在那之後,我遇到的另一個問題!

當我使用二傳手風格的一些屬性值設置爲DP1,我收到了空引用異常,說myUserControl1財產仍然是空的加載事件。我該如何解決它? -謝謝。

回答

1

我想你還沒有清楚的關於WPF的想法。

由於你的方法比功能性更像「winforms-like」,所以你遇到了很多麻煩。 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,或-at最不通知通過任何變化INotifyPropertyChanged模式。

語法描繪結合正常:SomeProperty = DP1,但是反之則不行。如果您需要雙向映射,則應在「綁定」子句中添加「Mode = TwoWay」。

如果您想自定義這兩個屬性映射功能,只需通過的IValueConverter接口定義自己的轉換器,然後聲明它在XAML。

在這裏你會發現一些有用的信息:http://msdn.microsoft.com/en-us/library/ms752347.aspx

乾杯

+0

感謝@Mario。這非常有用。 – Mimi

相關問題