2012-09-27 32 views
1

我在WPF中的應用程序中遇到了一個非常奇怪的問題,其中很多屏幕在綁定和組合框中工作得很好。但其中一個正在導致我的問題。ListView滾動觸發器Combobox SelectedValue並拋出異常

我創建了一個屏幕來爲應用中定義的每個用戶定義一個配置文件。所以它是一個Listview,每行都是一個標籤(用戶名)和一個帶有配置文件列表的組合框。 一切都是通過綁定來定義的。

這裏是爲ListView的XAML(我刪除樣式):

<ListView Name="lv_UserProfils" ItemsSource="{Binding ListeEntites}" AlternationCount="2" 
ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto"> 
    <ListView.View> 
     <GridView> 
      <GridViewColumn Header="Nom d'utilisateur" Width="250"> 
       <GridViewColumn.CellTemplate> 
        <DataTemplate> 
         <Border Height="25"> 
          <TextBlock Text="{Binding UserLogin}" Width="Auto" /> 
         </Border> 
        </DataTemplate> 
       </GridViewColumn.CellTemplate> 
      </GridViewColumn> 
      <GridViewColumn Header="Profil" Width="Auto"> 
       <GridViewColumn.CellTemplate> 
        <DataTemplate> 
         <ComboBox 
             ItemsSource="{Binding DataContext.ListeProfils, ElementName=lv_UserProfils}" 
             DisplayMemberPath="LibProfil" SelectedValuePath="IdProfil" 
             SelectedValue="{Binding Profil.IdProfil}" 
             SelectedItem="{Binding Profil}" Width="200" /> 
        </DataTemplate> 
       </GridViewColumn.CellTemplate> 
      </GridViewColumn> 
     </GridView> 
    </ListView.View> 
</ListView> 

DataContext是一個自定義視圖模型類的實例,它提供了一個ObservableCollection<UserBE>命名ListeEntites

UserBE是多還是少:

public sealed class UserBE 
{ 
public bool IsAdmin { get; set; } 
public bool IsUpdateGranted { get; set; } 

private string _userLogin; 
public string UserLogin 
{ 
    get { return _userLogin; } 
    set { _userLogin = value; OnPropertyChanged("UserLogin"); } 
} 

private ProfilBE _profil; 
public ProfilBE Profil 
{ 
    get { return _profil; } 
    set 
    { 
     _profil = value; 
     OnPropertyChanged("Profil"); 
    } 
} 
} 

而且ProfilBE

public sealed class ProfilBE 
{ 
    public long IdProfil { get; set; } 

    private string _codProfil; 
    public string CodProfil 
    { 
     get { return _codProfil; } 
     set { _codProfil = value; OnPropertyChanged("CodProfil"); } 
    } 

    private string _libProfil; 
    public string LibProfil 
    { 
     get { return _libProfil; } 
     set { _libProfil = value; OnPropertyChanged("LibProfil"); } 
    } 
} 

這是我的問題:
用戶列表很長,所以有一個滾動條。我可以儘可能多地滾動,但只要向上滾動(但只有當我向下滾動時),所有未顯示的組合框一出現在屏幕上就會被清除。

有趣的事實:

  • 當我滾動時,將Profil制定者不斷呼籲與顯示的行相關聯的對象。我不知道爲什麼(沒有原因,Profil財產已被定義)
  • 在一個點上,如果我向上滾動,我得到了很多的異常的,和Profil制定者開始接受null作爲價值

System.Windows.Data Error: 23 : Cannot convert 'BanquePrivee.AssuranceVie.Net.BE.ProfilBE' from type 'ProfilBE' to type 'System.Int64' for 'fr-FR' culture with default conversions; consider using Converter property of Binding. NotSupportedException:'System.NotSupportedException: Int64Converter cannot convert from BanquePrivee.AssuranceVie.Net.BE.ProfilBE. 
    at System.ComponentModel.TypeConverter.GetConvertFromException(Object value) 
    at System.ComponentModel.TypeConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value) 
    at System.ComponentModel.BaseNumberConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value) 
    at MS.Internal.Data.DefaultValueConverter.ConvertHelper(Object o, Type destinationType, DependencyObject targetElement, CultureInfo culture, Boolean isForward)' 

System.Windows.Data Error: 7 : ConvertBack cannot convert value 'BanquePrivee.AssuranceVie.Net.BE.ProfilBE' (type 'ProfilBE'). BindingExpression:Path=Profil.IdProfil; DataItem='UserBE' (HashCode=59629589); target element is 'ComboBox' (Name=''); target property is 'SelectedValue' (type 'Object') NotSupportedException:'System.NotSupportedException: Int64Converter cannot convert from BanquePrivee.AssuranceVie.Net.BE.ProfilBE. 
    at MS.Internal.Data.DefaultValueConverter.ConvertHelper(Object o, Type destinationType, DependencyObject targetElement, CultureInfo culture, Boolean isForward) 
    at MS.Internal.Data.ObjectTargetConverter.ConvertBack(Object o, Type type, Object parameter, CultureInfo culture) 
    at System.Windows.Data.BindingExpression.ConvertBackHelper(IValueConverter converter, Object value, Type sourceType, Object parameter, CultureInfo culture)' 

這很明顯,SelectedValue="{Binding Profil.IdProfil}"是問題,但我不明白爲什麼。
我不明白爲什麼在某些時候它會試圖將IdProfil轉換爲ProfilBE。我不應該在那裏使用一個轉換器。
我做了很多測試,數據似乎沒有問題(沒有空值,應該沒有的地方等)

有人能指出我在哪裏做錯了什麼嗎?

回答

0

結合。 但是,當我嘗試向上滾動時,它似乎試圖做一些對虛擬化並且即將在屏幕上再次出現的項目不起作用的東西。

我使用的解決辦法是禁用虛擬化用於使用VirtualizingStackPanel.IsVirtualizing="False" ListView中。它有一個小的性能打擊,但現在它的工作。

<ListView Name="lv_UserProfils" ItemsSource="{Binding ListeEntites}" AlternationCount="2" VirtualizingStackPanel.IsVirtualizing="False" 
     ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto"> 
    <ListView.View> 
     [...] 
    </ListView.View> 
</ListView> 
1

我認爲它與設置SelectedValueSelectedItem都有關。兩個屬性都做同樣的事情:他們設置選定的項目。但是,根據SelectedValuePath的設置,Value會將其設置爲Value,另一個只是將其設置爲ItemsSource中的項目。

我猜測,WPF是取得了一些困惑,並試圖設置SelectedValue(這是一個int)至SelectedItem,這是ProfilBE類型,異常被拋出,因爲ProfilBE不能轉換爲int。

但不管怎麼說,解決它嘗試刪除SelectedItem WPF是虛擬化當前沒有顯示的對象在你的組合框

<ComboBox ItemsSource="{Binding DataContext.ListeProfils, ElementName=lv_UserProfils}" 
    DisplayMemberPath="LibProfil" SelectedValuePath="IdProfil" 
    SelectedValue="{Binding Profil.IdProfil}" 
    Width="200" /> 
+0

明天我再試一次,但我覺得如果沒有這兩種方法,我不會按照我想要的方式工作。我在應用程序中的任何地方都使用這種代碼,而當它不在滾動列表視圖中時,它似乎可以工作。我認爲,如果你不指定它將嘗試改變當前的'UserBE.Profil.IdProfil'值,而我想要的是用選定的一個替換完整的'UserBE.Profil'對象。 –

+0

@JulienN兩種方法做同樣的事情,但如果你想使用'SelectedItem',而不是'SelectedValue'和'SelectedValuePath'然後是確保該項目是指存儲在您的ItemsSource的項目之一完全相同的參考或WPF不會考慮它的匹配和選擇項目(或者你可以覆蓋.Equals()ProfileBE的方法,如果'IdProfil'匹配返回true) – Rachel

+0

我同意,但對象是不一樣的,他們是未在相同位置初始化。唯一的「關係」是ID。但是重寫'Equals()'本來就是一個很好的解決方案來取代我對Combobox屬性的雙重使用(不確定它是否會解決我的問題)。我應該從一開始就這樣做:) –