2010-03-03 52 views
2

我注意到ComboBox獲取可視化樹時ComboBox.ItemsSource上的靜態和動態資源之間的行爲差​​異。Combobox.ItemsSource上的StaticResource vs DynamicResource行爲

    靜態爲例選定的目標
  • 仍然
  • 在動態爲例
  • ,底層對象獲得一個空值

綁定看起來不錯,因爲當組合框獲得焦點,並有自己SelectedIndex已更改,將更改正確通知給另一個列表 - 兩個對象都實現INotifyProperty - 兩個List都是ObservableCollections。

這是當動態綁定組合框獲得了焦點的是,奇怪的事情發生

XAML

<Window ... xmlns:me = "clr-namespace:WpfComboBoxBug"> 
    <Window.Resources> 
     <me:ShippingList x:Key="sl" /> 
     <me:DestinationList x:Key="dl" /> 
    </Window.Resources> 
    <Grid x:Name="LayoutRoot"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="21" /> 
      <RowDefinition Height="421*" /> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="*" /> 
      <ColumnDefinition Width="*" /> 
     </Grid.ColumnDefinitions> 
     <Custom:DataGrid Grid.Row="1" 
      ItemsSource="{StaticResource sl}" x:Name="dg" AutoGenerateColumns="False" Grid.RowSpan="2"> 
     <Custom:DataGrid.Columns> 
      <Custom:DataGridTextColumn Header="Reference" Binding="{Binding Reference}" /> 
      <Custom:DataGridTemplateColumn Header="Destination"> 
       <Custom:DataGridTemplateColumn.CellTemplate> 
       <DataTemplate> 
        <TextBlock Text="{Binding Destination.Name}"></TextBlock> 
       </DataTemplate> 
       </Custom:DataGridTemplateColumn.CellTemplate> 
       <Custom:DataGridTemplateColumn.CellEditingTemplate> 
       <DataTemplate> 
        <ComboBox ItemsSource="{StaticResource dl}" SelectedItem="{Binding Destination,Mode=TwoWay}" DisplayMemberPath="Name"/> 
       </DataTemplate> 
       </Custom:DataGridTemplateColumn.CellEditingTemplate> 
      </Custom:DataGridTemplateColumn> 
     </Custom:DataGrid.Columns> 
     </Custom:DataGrid> 
      <Custom:DataGrid Grid.Column="1" Grid.Row="1" ItemsSource="{StaticResource sl}" x:Name="dg2" AutoGenerateColumns="False" Grid.RowSpan="2"> 
      <Custom:DataGrid.Columns> 
       <Custom:DataGridTextColumn Header="Reference" Binding="{Binding Reference}" /> 
       <Custom:DataGridTemplateColumn Header="Destination"> 
        <Custom:DataGridTemplateColumn.CellTemplate> 
         <DataTemplate> 
          <TextBlock Text="{Binding Destination.Name}"></TextBlock> 
         </DataTemplate> 
        </Custom:DataGridTemplateColumn.CellTemplate> 
        <Custom:DataGridTemplateColumn.CellEditingTemplate> 
         <DataTemplate> 
          <ComboBox ItemsSource="{DynamicResource dynamicdl}" SelectedItem="{Binding Destination,Mode=TwoWay}" DisplayMemberPath="Name"/> 
         </DataTemplate> 
        </Custom:DataGridTemplateColumn.CellEditingTemplate> 
       </Custom:DataGridTemplateColumn> 
      </Custom:DataGrid.Columns> 
     </Custom:DataGrid> 
     <TextBox Height="23" Name="textBox1" VerticalAlignment="Top" Text="Static" /> 
     <TextBox Height="23" Name="textBox2" VerticalAlignment="Top" Text="Dynamic" Grid.Column="2" /> 
    </Grid> 
</Window> 

CS

using System; 
/* snip */ 

namespace WpfComboBoxBug 
{ 
    /// <summary> 
    /// Logique d'interaction pour MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      ShippingList sl; 
      this.InitializeComponent(); 
      sl = this.Resources["sl"] as ShippingList; 

      ResourceDictionary rd = new ResourceDictionary(); 
      rd.Add("dynamicdl", this.FindResource("dl")); 

      dg2.Resources = rd; 


      dg.ItemsSource = CollectionViewSource.GetDefaultView(sl); 
      dg2.ItemsSource = CollectionViewSource.GetDefaultView(sl); 
     } 
    } 
} 

完整的源代碼在:http://dl.free.fr/eI1VtkaB8 (VS 2008 SP1,.NET 3.5 SP1)

我希望動態資源在這種情況下表現得像靜態資源,因爲我在開始時初始化它一次。

  • 我在這裏發現了一個錯誤嗎?
  • 如果不是這樣,你會如何解釋這種差異?
+0

當問這樣的問題時,如果將代碼的相關部分粘貼到問題中,而不是將其放入zip文件中,您將得到更好的答案。我們中的很多人(包括我自己)都在快速查看問題,無法下載單獨的zip文件。粘貼時,縮進四個字符,以便您的代碼格式正確。文本輸入框上方有一個按鈕可以執行此操作。 – 2010-03-03 17:24:47

回答

3

我不得不看看你的代碼是肯定的,但我猜你的ComboBox有它的SelectedItem或SelectedValue雙向綁定到屬性。

當您使用StaticResource時,會在XAML加載時解析資源引用。當您使用DynamicResource時,稍後解決資源引用問題。所以可能發生的是你的ComboBox啓動時沒有任何項目,這會迫使它的SelectedItem和SelectedValue爲空。雙向綁定導致屬性使用此值進行更新。

就我個人而言,我認爲ComboBox無法優雅地處理這種情況是ComboBox設計中的一個錯誤,而不是實現錯誤。

對於我自己的項目,我經常使用我創建的ComboBox和ListBox增強功能來解決此問題:我可以使用其他屬性來代替SelectedValue和SelectedItems。我的新屬性接受任何值,直到ItemsSource被設置,之後它保持與​​SelectedValue或SelectedItem同步。

您可以使用類似的技術,或者只是始終確保ItemsSource在SelectedValue或SelectedItem之前被綁定/初始化。

更新

當控制從視覺樹中刪除,一切都發生在相反:ItemsSource時立即因祖先變化清除,那麼DataContext的被清除。在此期間,ComboBox有一個空的SelectedItem,它傳播到綁定的屬性。

帶有額外的SelectedItem和SelectedValue屬性的增強型ComboBox或ListBox類也可以解決此問題:每當ItemsSource爲非null時它應該使SelectedItem/SelecteValue與自定義屬性保持同步,並且每當ItemsSource爲null時解除耦合。

+0

感謝您的幫助。但這裏的要點是在聯合國約束時間比在約束時間 – 2010-03-04 08:48:24

+1

我明白你的意思。當我讀到你的問題時,我錯過了。我所說的幾乎所有東西都適用。我已經添加了一些關於處理在您描述爲「UN-binding」(從可視樹中刪除控件)期間發生的問題的更多信息。 – 2010-03-04 15:04:09