2012-07-23 189 views
4

我有一個控制,具有依賴屬性「IsLightOnVal」女巫是這樣定義:綁定觸發元素父集合的

// List of available states for this control 
private ObservableCollection<CtlStateBool> m_IsLightOnVal; 

[Category("Properties")] 
public System.Collections.ObjectModel.ObservableCollection<CtlStateBool> IsLightOnVal 
{ 
    get 
    { 
     if (m_IsLightOnVal == null) 
      m_IsLightOnVal = new System.Collections.ObjectModel.ObservableCollection<CtlStateBool>(); 
     return m_IsLightOnVal; 
    } 
    set 
    { 
     if (m_IsLightOnVal != value) 
     { 
      m_IsLightOnVal = value; 
      OnPropertyChanged("IsLightOnVal"); 
     } 
    } 
} 

// IsLightOnVal dependency property. 
public static readonly DependencyProperty IsLightOnValProperty = 
     DependencyProperty.Register("IsLightOnVal", typeof(System.Collections.ObjectModel.ObservableCollection<CtlStateBool>), typeof(ButtonSimple), new UIPropertyMetadata(new System.Collections.ObjectModel.ObservableCollection<CtlStateBool>())); 

在我的收藏,每個元素包含一個字符串(州)和布爾(Value)

我的控件風格在ControlTemplate中定義。

我想添加一個觸發器,例如,當我的集合中的第一個元素爲true時,然後執行一些操作。

我嘗試這樣做:

<Style x:Key="Btn_RADIO_VHF" TargetType="{x:Type ButtonSimple}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
     <ControlTemplate TargetType="{x:Type ButtonSimple}"> 
      <Canvas .../> 
      <ControlTemplate.Triggers> 
       <DataTrigger Value="True" Binding="{Binding IsLightOnVal[0].Value, RelativeSource={RelativeSource TemplatedParent}}"> 
        <Setter Property="Fill" TargetName="pShowTouch" Value="{DynamicResource ShowTouch}"/> 
       </DataTrigger> 
      </ControlTemplate.Triggers> 

我也試過用一個簡單的觸發器,而不是一個DataTrigger,但它似乎不支持綁定...

有人能幫助我嗎?

回答

4

你有一些問題存在。首先,您正在使用RelativeSourceTemplatedParent但這不是綁定應用於模板中的元素,因此您應該使用。這樣可以固定相對容易:

<DataTrigger Value="True" Binding="{Binding Path=IsLightOnVal[0].Value, RelativeSource={RelativeSource Self}}"> 

其次,你必須定義這個屬性既作爲CLR屬性(有自己的後備存儲)和一個DependencyProperty。如果該屬性被定義爲DP,那麼該框架將期望您使用DP來存儲該值。在您的代碼中,您從不使用SetValue方法實際將集合實例存儲在DependencyObject的後備存儲中。因此,有許多方法來解決這個問題:

1)拆下DP:

//public static readonly DependencyProperty IsLightOnValProperty = 
//  DependencyProperty.Register("IsLightOnVal", typeof(System.Collections.ObjectModel.ObservableCollection<CtlStateBool>), typeof(ButtonSimple), new UIPropertyMetadata(new System.Collections.ObjectModel.ObservableCollection<CtlStateBool>())); 

因爲它不是一個DP雖然你將無法將其設置在一個二傳手,將其綁定到虛擬機上的一些屬性等等,所以這可能不是最好的選擇。

2)存儲在DP值以及局部變量:

public System.Collections.ObjectModel.ObservableCollection<CtlStateBool> IsLightOnVal 
{ 
    get 
    { 
     if (m_IsLightOnVal == null) 
      this.SetValue(IsLightOnValProperty, m_IsLightOnVal = new System.Collections.ObjectModel.ObservableCollection<CtlStateBool>()); 
     return m_IsLightOnVal; 
    } 
    set 
    { 
     if (m_IsLightOnVal != value) 
     { 
      this.SetValue(IsLightOnValProperty, m_IsLightOnVal = value); 
      OnPropertyChanged("IsLightOnVal"); 
     } 
    } 
} 

我個人不喜歡這個選項。或者更具體地說,我認爲它的糟糕做法是在吸氣人員中懶散地分配你自己的財產。如果某人實際設置了較低的優先級(例如,在模板中定義了一個實例並且在該模板中定義了屬性集/綁定),則會在該對象上設置一個本地值,該值可能會覆蓋實際值。如果你計劃在設計時支持這可能會弄亂設計師。如果你確實走這條路線,那麼你真的應該在你的DP定義中添加一個PropertyChangedHandler,並且確保你的m_IsLightOnVal成員變量在那裏,否則如果這個值是通過DP設置的,你就會失去同步。 WPF框架 - 使用SetValue來設置屬性的值)。

3)僅使用的GetValue /的SetValue

public System.Collections.ObjectModel.ObservableCollection<CtlStateBool> IsLightOnVal 
{ 
    get { return (System.Collections.ObjectModel.ObservableCollection<CtlStateBool>)this.GetValue(IsLightOnValProperty); } 
    set { this.SetValue(IsLightOnValProperty, value); } 
} 

我會推薦這種方法。是的,這意味着任何希望設置該屬性的人都必須定義該集合的一個實例,但我認爲這比您設置自己的DP值時可能遇到的問題更可取。請注意,如果您採用此路線,那麼您可能需要定義一個派生自ObservableCollection的非泛型集合類,以便有人可以在xaml中定義集合類的實例,但如果您希望這種綁定僅限於此,可能不是問題。從另一個回覆的評論,儘管它聽起來像它可能被設置在XAML。

4

現在您的觸發器從不觸發,因爲ObservableCollection不支持屬性更改通知包含的元素。

你可以嘗試實施的ObservableCollection專業化支持ChangeNotification這裏看到例如Extending ObservableCollection

但是,它可能是更容易的ObservableCollection的第一個值存儲在您的視圖模型/代碼後面,將其設置爲觸發器的目標。

+0

謝謝,但我只是寫了一個例子,我們的圖形設計師將使用這個集合來添加他所需要的項目,然後他需要將它們綁定到圖形上。因此,他可以通過更改集合中的值並保持始終相同的樣式來重複使用相同樣式的多個項目。 – mlemay 2012-07-23 14:41:25

1

發現:

<DataTrigger Binding="{Binding MyCollection[index].Value, RelativeSource={RelativeSource Self}}" Value="True"> 
    <Setter .../> 
</DataTrigger>