2016-02-01 40 views
1

我正在使用ContentControl更改顯示在我的UI中的控件,具體取決於用戶通過DataTemplateSelector選擇的對象類型。卸載控件時無法獲取附加行爲屬性值

當控件被卸載時,基於替換下面的ContentControl中的內容,我無法再訪問 附加行爲的附加行爲的Unloaded事件處理程序的屬性。

例如,如果用戶點擊鑽取單位然後點擊用戶界面中的燃料卡車單位,那麼我無法訪問控件中的附加屬性。它就像控制器卸載時一樣,在DateTemplateSelector激發時讀取附加屬性 已經太晚了。

如果控件因爲關閉父窗口或其他原因(如阻止父文檔選項卡)而被卸載,那麼我讀取附加的行爲屬性值時沒有問題。

這是錯誤的代碼片段:

的代碼試圖找到附加的行爲屬性:「行爲:PersistUiBehavior.PersistanceChildCode」從下面 和我期待的「結果」等於17或18取決於控件處於活動狀態時。

public static void GetPersistenceRequiredControls(DependencyProperty property, DependencyObject root, int code, List<object> sources) 
{ 
    if ((property != null) && (root != null)) 
    { 
    // property = behaviours:PersistUiBehavior.PersistanceChildCode does not exist here when unloaded 
    var result = (int) root.GetValue(property); 
    if (result == code) 
    { 
     sources.Add(root); 
    } 
    } 
} 

這裏是一個XAML片段顯示的各個部分:

<UserControl x:Class="FleetControl.Editors.Views.PropertyEditor"> 
<UserControl.Resources> 
    <ResourceDictionary> 

    <templates:PropertyEditorTemplateSelector x:Key="PropertyEditorTemplateSelector"> 

    <templates:PropertyEditorTemplateSelector.DrillUnitEditorTemplate> 
     <DataTemplate> 
     <telerik:RadPropertyGrid 
      x:Name="DrillPropertyGrid" 
      behaviours:PersistUiBehavior.FileName="Test1.txt" 
      behaviours:PersistUiBehavior.PersistanceParentCode="5" 
      behaviours:PersistUiBehavior.PersistanceChildCode="17" 
      behaviours:PersistUiBehavior.Name="DrillPropertyGrid"> 
      <telerik:RadPropertyGrid.PropertyDefinitions> 
      <telerik:PropertyDefinition DisplayName="Equipment Ident" Binding="{Binding DisplayName, Mode=OneWay}" GroupName="Description" IsReadOnly="True" /> 
      <telerik:PropertyDefinition DisplayName="Equipment Description" Binding="{Binding Description, Mode=OneWay}" GroupName="Description" IsReadOnly="True"/> 
      <telerik:PropertyDefinition DisplayName="Equipment Type Ident" Binding="{Binding EquipmentType.Ident, Mode=OneWay}" GroupName="Description" IsReadOnly="True"/> 
      </telerik:RadPropertyGrid.PropertyDefinitions> 
     </telerik:RadPropertyGrid> 
     </DataTemplate> 
    </templates:PropertyEditorTemplateSelector.DrillUnitEditorTemplate> 
    <templates:PropertyEditorTemplateSelector.FuelTruckUnitEditorTemplate> 
     <DataTemplate> 
     <telerik:RadPropertyGrid 
      x:Name="FuelTruckUnitPropertyGrid" 
      behaviours:PersistUiBehavior.FileName="Test2.txt" 
      behaviours:PersistUiBehavior.PersistanceParentCode="6" 
      behaviours:PersistUiBehavior.PersistanceChildCode="18" 
      behaviours:PersistUiBehavior.Name="FuelTruckUnitPropertyGrid"> 
      <telerik:RadPropertyGrid.PropertyDefinitions> 
      <telerik:PropertyDefinition DisplayName="Location" Binding="{Binding Location.LocationName, Mode=OneWay}" GroupName="Realtime" IsReadOnly="True"/> 
      <telerik:PropertyDefinition DisplayName="Location Code" Binding="{Binding Location.Code, Mode=OneWay}" GroupName="Realtime" IsReadOnly="True"/> 
      <telerik:PropertyDefinition DisplayName="Location Description" Binding="{Binding Location.Description, Mode=OneWay}" GroupName="Realtime" IsReadOnly="True"/> 
      </telerik:RadPropertyGrid.PropertyDefinitions> 
     </telerik:RadPropertyGrid> 
     </DataTemplate> 
    </templates:PropertyEditorTemplateSelector.FuelTruckUnitEditorTemplate> 
    </templates:PropertyEditorTemplateSelector> 

</ResourceDictionary> 
</UserControl.Resources> 

<Grid> 
    <Grid.RowDefinitions> 
    <RowDefinition Height="*" /> 
    </Grid.RowDefinitions> 
    <Grid.ColumnDefinitions> 
    <ColumnDefinition Width="*" /> 
    </Grid.ColumnDefinitions> 

    <ContentControl 
    ContentTemplateSelector="{StaticResource PropertyEditorTemplateSelector}" 
    Content="{Binding Path=SelectedPropertyEditor, Mode=OneWay}" /> 
</Grid> 
</UserControl> 

回答

2

是的,你是正確的。當ContentPresenter的模板更改時,會清除附加屬性(實際上是所有屬性)。這是由System.Windows.StyleHelper.DoTemplateInvalidations()方法執行的操作的一部分,在這種情況下由ContentPresenter.OnTemplateChanged()方法調用。這最終導致System.Windows.StyleHelper.InvalidatePropertiesOnTemplateNode()被調用,這是實際工作完成的地方。

例如,這裏的調用堆棧我在調試器中看到:

WindowsBase.dll!System.Windows.DependencyObject.InvalidateProperty(System.Windows.DependencyProperty dp, bool preserveCurrentValue) Unknown 
PresentationFramework.dll!System.Windows.StyleHelper.InvalidatePropertiesOnTemplateNode(System.Windows.DependencyObject container, MS.Internal.FrameworkObject child, int childIndex, ref MS.Utility.FrugalStructList<System.Windows.ChildRecord> childRecordFromChildIndex, bool isDetach, System.Windows.FrameworkElementFactory templateRoot) Unknown 
PresentationFramework.dll!System.Windows.StyleHelper.ClearTemplateChain(System.Collections.Specialized.HybridDictionary[] instanceData, System.Windows.FrameworkElement feContainer, System.Windows.FrameworkContentElement fceContainer, System.Collections.Generic.List<System.Windows.DependencyObject> templateChain, System.Windows.FrameworkTemplate oldFrameworkTemplate) Unknown 
PresentationFramework.dll!System.Windows.StyleHelper.ClearGeneratedSubTree(System.Collections.Specialized.HybridDictionary[] instanceData, System.Windows.FrameworkElement feContainer, System.Windows.FrameworkContentElement fceContainer, System.Windows.FrameworkTemplate oldFrameworkTemplate) Unknown 
PresentationFramework.dll!System.Windows.StyleHelper.DoTemplateInvalidations(System.Windows.FrameworkElement feContainer, System.Windows.FrameworkTemplate oldFrameworkTemplate) Unknown 
PresentationFramework.dll!System.Windows.Controls.ContentPresenter.OnTemplateChanged(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs e) Unknown 

這一切發生被稱爲Unloaded事件之前。無論好壞,這完全是由設計。

沒有一個很好的Minimal, Complete, and Verifiable example,它清楚地顯示了你的代碼的作用,並精確地解釋了你的代碼做的最終目標是什麼,我不能說真正的替代方法是什麼。

至少有幾個明顯的變通的浮現在腦海中,都涉及到在時間上有些早一點執行你試圖在Unloaded事件處理程序做的工作:

  • 做的工作時,模型數據參考更改。即處理對SelectedPropertyEditor屬性的更改。
  • 當附加屬性本身失效時進行工作。例如。將PropertyChangedCallback委託人添加到您附加的屬性元數據中,並在那裏完成工作(即,當您看到附加屬性從以前的某個值更改爲null時)。

我會注意到,在您發佈的代碼點點,看來你想掛到在宣佈DependencyObject模板本身(例如在telerik:RadPropertyGrid對象)。恕我直言,這可能會導致其他問題在別處。我承認,我不知道確切地說有什麼問題,但在WPF已經卸載它之後,嘗試訪問模板子圖並重新生成它似乎是錯誤的。因此,即使您解決了屬性失效問題,但當您嘗試重用該對象時,您可能會在稍後遇到更多問題。


如果你需要比這更具體的幫助,請在您已與精確的細節,以專門你要當模板被卸載到發生什麼事提供了良好的代碼示例,沿着新問題,以及您希望在卸載後如何能夠使用模板對象。